javascript - 使用 useReducer 和 useContext,在分派(dispatch)操作时不会重新呈现组件。如何触发重新渲染?

标签 javascript reactjs react-hooks

我是 React 的初学者,我正在研究如何一起使用 useReducer 和 useContext。 我正在研究的非常简单的研究示例只是一个名为 Greeting 的组件,它获取从 StateContext 传递的状态,它显示 Main.js 中的用户名 (Mike),并且它有一个按钮应该将操作分派(dispatch)给将名字更改为约翰。 问题是,单击按钮时没有任何反应,并且问候语组件中的名称保持不变。 我注意到,一旦调度了操作changeName,Greeting 组件内的console.log 就不会被触发,这意味着我相信Greeting 组件不会重新渲染。 为什么问候语没有重新渲染并显示更新的名称

这是主要组件:

import React, { useReducer } from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';

// components
import StateContext from './components/StateContext';
import DispatchContext from './components/DispatchContext';
import Greeting from './components/Greeting';

function reducer(state, action) {
  switch (action.type) {
    case 'changeName':
      const newState = state;
      newState.name = action.name;
      return newState;
    default:
      return;
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, {
    name: 'Mike',
  });
  console.log('name', state.name);
  return (
    <BrowserRouter>
      <Switch>
        <StateContext.Provider value={state}>
          <DispatchContext.Provider value={dispatch}> 
            <Route path="/greeting">
              <Greeting />
            </Route>
          </DispatchContext.Provider>
        </StateContext.Provider>
      </Switch>
    </BrowserRouter>
  );
}

export default App;

这是问候语组件:

import React, { useContext } from 'react';
import StateContext from './StateContext';
import DispatchContext from './DispatchContext';

const Greeting = () => {
  const state = useContext(StateContext);
  const appDispatch = useContext(DispatchContext);
  console.log('inside greeting component', state.name)

  return (
    <>
      <div>{state.name}</div>
      <button onClick={() => appDispatch({ type: 'changeName', name: 'John' })}>
        Change Name
      </button>
    </>
  );
};

export default Greeting;
 

调度上下文:

import { createContext } from 'react';

const DispatchContext = createContext();

export default DispatchContext;

状态上下文:

import { createContext } from 'react'

const StateContext = createContext()

export default StateContext

最佳答案

问题

这里的问题是状态对象突变。

function reducer(state, action) {
  switch (action.type) {
    case 'changeName':
      const newState = state;      // <-- newState is reference to state
      newState.name = action.name; // <-- mutation!!
      return newState;             // <-- same state reference
    default:
      return;
  }
}

当您改变该状态对象并返回它时,它仍然是对先前状态的引用,因此 React 会放弃重新渲染它。

解决方案

返回一个新的状态对象。将先前的状态浅复制到新的状态对象中,然后更新嵌套属性。如果状态更新嵌套得更深,那么您还需要浅复制任何更新的嵌套状态。不要忘记在默认情况下返回当前状态对象。

function reducer(state, action) {
  switch (action.type) {
    case 'changeName':
      return {
        ...state,
        name: action.name
      };

    default:
      return state;
  }
}

关于javascript - 使用 useReducer 和 useContext,在分派(dispatch)操作时不会重新呈现组件。如何触发重新渲染?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67732787/

相关文章:

javascript - 我想调用javascript函数,当选择选项(它基于for循环)仅被选择一次时

javascript - 如何开始使用 React 进行函数式编程?

javascript - React 重新渲染次数过多

javascript - 如何在 React JS 中实时显示时间和日期?

javascript - Jest( react 测试工具)错误 - 解析错误 : Line 1: Illegal import declaration

reactjs - react 无效的钩子(Hook)调用错误和故事书6

javascript - Redux表格: How to submit before function is triggered?

javascript - 从服务器到客户端 Node.js 的文件传输

javascript - React 应用程序中的 addEventListener 不起作用

node.js - 在 Mac 终端上找不到 jsx 命令