主題提供者問題 (Theme Provider issue)


問題描述

主題提供者問題 (Theme Provider issue)

我正在嘗試為一個小項目設置主題提供程序。每次用戶單擊按鈕時,應用程序主題(顏色)都應該改變。假設我在一個單獨的文件中有四個主題,如下所示:

const themesArray = [
    { primaryColor: '#483639', secondaryColor: '#F7F7F7' },
    { primaryColor: '#fb7051', secondaryColor: '#333' },
    { primaryColor: '#60b494', secondaryColor: '#F7F7F7' },
    { primaryColor: '#afb5c0', secondaryColor: '#333' }
];

export default themesArray;

每次用戶單擊按鈕(嵌套在特定組件中)時,計數器都會遞增,直到 3,如下所示:

p>
import React, { useState, useContext } from 'react';
import themesArray from '../../styles/themesArray';

const ThemeContext = React.createContext();
const ThemeUpdateContext = React.createContext();

const useTheme = () => useContext(ThemeContext);
const useThemeUpdate = () => useContext(ThemeUpdateContext);

const ThemeProvider = ({ children }) => {

    const [state, setState] = useState({
        count: 0,
        primaryColor: themesArray[0].primaryColor,
        secondaryColor: themesArray[0].secondaryColor
    });

    const toggleTheme = () => {
        setState(prevState => ({
            count: prevState.count >= 3 ? 0 : ++prevState.count,
            primaryColor: themesArray[prevState.count].primaryColor,
            secondaryColor: themesArray[prevState.count].secondaryColor
        }));
    }

    return (
        <ThemeContext.Provider value={[state.primaryColor, state.secondaryColor]}>
            <ThemeUpdateContext.Provider value={toggleTheme}>
                {children}
            </ThemeUpdateContext.Provider>
        </ThemeContext.Provider>
    );

}

export { ThemeProvider, useTheme, useThemeUpdate };

計數器似乎工作正常,但問題是我永遠不會回到我的第一個對象值(我永遠不會回到第一個主題顏色)。我的意思是當我 console.log(state.count, state.primaryColor, state.secondaryColor) 我得到這個:

0 #483639 #F7F7F7 ThemeContext.js:24
1 #fb7051 #333 ThemeContext.js:24
2 #60b494 #F7F7F7 ThemeContext.js:24
3 #afb5c0 #333 ThemeContext.js:24
0 #afb5c0 #333 ThemeContext.js:24
1 #fb7051 #333 ThemeContext.js:24
2 #60b494 #F7F7F7 ThemeContext.js:24
3 #afb5c0 #333 ThemeContext.js:24
0 #afb5c0 #333 ThemeContext.js:24

你知道為什麼第一個對象的值會被最後一個對象覆蓋嗎每次計數器值回到0時的對象值?


參考解法

方法 1:

You are mutating the state ++prevState.count which is a problem.

Treat state as if it were immutable

Moreover you can use modulo instead:

const toggleTheme = () => {
    setState(prevState => {
      const nextCount = prevState.count + 1;
      return {
        count: nextCount % 3,
        primaryColor: themesArray[nextCount].primaryColor,
        secondaryColor: themesArray[nextCount].secondaryColor
      };
    });
  };

Full example:


const themesArray = [
  { primaryColor: "#483639", secondaryColor: "#F7F7F7" },
  { primaryColor: "#fb7051", secondaryColor: "#333" },
  { primaryColor: "#60b494", secondaryColor: "#F7F7F7" },
  { primaryColor: "#afb5c0", secondaryColor: "#333" }
];

const ThemeContext = React.createContext();
const ThemeUpdateContext = React.createContext();

const useTheme = () => useContext(ThemeContext);
const useThemeUpdate = () => useContext(ThemeUpdateContext);

const ThemeProvider = ({ children }) => {
  const [state, setState] = useState({
    count: 0,
    primaryColor: themesArray[0].primaryColor,
    secondaryColor: themesArray[0].secondaryColor
  });

  const toggleTheme = () => {
    setState(prevState => {
      const nextCount = prevState.count + 1;
      return {
        count: nextCount % 3,
        primaryColor: themesArray[nextCount].primaryColor,
        secondaryColor: themesArray[nextCount].secondaryColor
      };
    });
  };

  return (
    <ThemeContext.Provider value={[state.primaryColor, state.secondaryColor]}>
      <ThemeUpdateContext.Provider value={toggleTheme}>
        {children}
      </ThemeUpdateContext.Provider>
    </ThemeContext.Provider>
  );
};

const Button = () => {
  const [primaryColor] = useTheme();
  const toggle = useThemeUpdate();
  return (
    <button
      onClick={toggle}
      style={{ width: 500, height: 500, backgroundColor: primaryColor }}
    >
      Button
    </button>
  );
};

const App = () => {
  return (
    <ThemeProvider>
      <Button />
    </ThemeProvider>
  );
};

Edit brave‑sunset‑0xu96

(by chalatumDennis Vash)

參考文件

  1. Theme Provider issue (CC BY‑SA 2.5/3.0/4.0)

#react-context #react-hooks #javascript #reactjs #use-context






相關問題

在項目中使用 Context API 我以前會在異步操作創建者中使用 Redux? (Using Context API in a project I would have previously used Redux in - async action creators?)

Nextjs 和上下文 API (Nextjs and Context API)

從 redux-saga 函數訪問 React 上下文值 (Access React context value from redux-saga function)

如何在 Django 應用程序中用 react ContextAPI 替換 Redux (How can you replace Redux by the react ContextAPI in a Django App)

從深度嵌套的組件更新狀態而不重新渲染父組件 (Update state from deeply nested component without re-rendering parents)

更新 useContext 中的值時,組件不會重新呈現 (Component not re rendering when value from useContext is updated)

為什麼我無法從反應上下文訪問變量?你能找出錯誤嗎? (Why am I not able to access variable from react context? Can you identify the mistake?)

React Hook useEffect 缺少依賴項(在上下文中定義的函數) (React Hook useEffect has a missing dependency (function defined in context))

React Context 是道具鑽探的解毒劑嗎? (Is React Context an antidote for prop drilling?)

主題提供者問題 (Theme Provider issue)

打字稿反應上下文+類型'{}'沒有調用簽名 (Typescript react context + Type '{}' has no call signatures)

next.js socket.io 使用效果不更新套接字消息 (next.js socket.io useeffect not updating on socket message)







留言討論