'dispatch' 在 react 中使用 useReducer 和 useContext 时未定义

'dispatch' is not defined when using useReducer with useContext in react

我正在尝试找出如何使用 useContextuseReducer 调度方法从组件更改全局状态。

该组件只需单击即可更改页面的背景

这是我定义上下文的方式ThemeContext.js

import { createContext, useReducer } from "react";
import ThemeReducer from './ThemeReducer'

const INITIAL_STATE = {
    isLightTheme: true,
    light: {syntax: '#555', ui: '#ddd', bg: '#eee'},
    dark: {syntax: '#ddd', ui: '#333', bg: '#555'},
}

export const ThemeContext = createContext(INITIAL_STATE);

const ThemeContextProvider = ({ children }) => {
   const [state, dispatch] = useReducer(ThemeReducer, INITIAL_STATE);
    return ( 
        <ThemeContext.Provider value={{
            isLightTheme: state.isLightTheme,
            light: state.light,
            dark:  state.dark,
            dispatch,
        }}>
            {children}
        </ThemeContext.Provider>
     );
}     
export default ThemeContextProvider;

ThemeReducer.js是:

const ThemeReducer = (state, action) => {
    switch (action.type) {
      case "SET_DARK":
        return {
            isLightTheme: false,
        };    
      case "SET_LIGHT":
            return {
                isLightTheme: true,
            }; 
      default:
        return state;
    }
  };  
  export default ThemeReducer;

app.js:

function App() {
  return (
    <div className="App">
       <ThemeContextProvider>        
          <Navbar />
          <BookList />
          <ThemeToggle />
       </ThemeContextProvider>
    </div>
  );
}

export default App;

ThemeToggle.js 组件

const ThemeToggle = () => {

    return ( 
        <button onClick={()=>dispatch({type: "SET_DARK"})}>Change theme</button>
     );
}
 
export default ThemeToggle;

但是我得到这个错误:

src/components/ThemeToggle.jsx
  Line 6:30:  'dispatch' is not defined 

我不明白为什么。因为 dispatch 应该在上下文中。我想知道这里出了什么问题,我该如何解决?

P.S BooKList 组件。

import  { useContext } from 'react'
import { ThemeContext } from '../context/ThemeContext';


const BookList = () => {
    const {isLightTheme, light, dark} = useContext(ThemeContext)
    const theme = isLightTheme ? light : dark;
    return ( 
        <div  style={{background : theme.ui , color: theme.syntax}}>
            <ul>
                <li stryle={{background: theme.ui}} >The way of kings</li>
                <li stryle={{background: theme.ui}} >The namoe fot the wind</li>
                <li stryle={{background: theme.ui}} >The Final empire</li>
            </ul>
        </div>
     );
}

您似乎无法访问 ThemeToggle 中的 ThemeContext。使用 useContext 挂钩访问 ThemeContext 上下文值并解构 dispatch 函数。

const ThemeToggle = () => {
  const { dispatch } = useContext(ThemeContext);
  return ( 
    <button onClick={() => dispatch({type: "SET_DARK"})}>
      Change theme
    </button>
  );
}
 
export default ThemeToggle;

为了完整起见,将 dispatch 添加到默认上下文值。

const INITIAL_STATE = {
  isLightTheme: true,
  light: {syntax: '#555', ui: '#ddd', bg: '#eee'},
  dark: {syntax: '#ddd', ui: '#333', bg: '#555'},
  dispatch: () => {},
}

export const ThemeContext = createContext(INITIAL_STATE);

ThemeReducer reducer 函数正在剥离集合 light/dark 案例中的状态。您需要保留现有状态。

const ThemeReducer = (state, action) => {
  switch (action.type) {
    case "SET_DARK":
      return {
        ...state,
        isLightTheme: false,
      };
  
    case "SET_LIGHT":
      return {
        ...state,
        isLightTheme: true,
      };

    default:
      return state;
  }
};