我是 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/