我正在尝试在不重新加载整个应用程序的情况下更改状态。由于某种原因,这没有发生,当我设置甚至没有传递给特定组件的对象的状态时,该组件会无缘无故地更新。
所以在下面的代码中,我在设置消息时,MainContent
不应该重新加载。
const [message, setMessage] = useState({});
setMessage('my message'); // This causes the entire app, including 'MyComponent' to reload
return (
<div className='App'>
<Header user={user} message={message} setMessage={setMessage} />
<div id='main-site'>
<Switch>
// SHOULD NOT RELOAD UNLESS PASSED IN PROP CHANGED
<Route path='/main' component={MainContent} />
</Switch>
</div>
</div>
);
标题.jsx
return (
{message && (
<div>
<span>{message.text}</span>
// This on click makes the entire app reload
<button className='close' onClick={() => setMessage({})}>
X
</button>
</div>
)}
);
如何确保只有具有message
prop 的组件得到更新,并且没有其他组件重新渲染?
有两种方法可以解决您的问题。
第一个涉及将您的状态向下移动到子组件,即标头,因为只有标头使用message
状态。要记住的另一件事是,您不要直接在渲染中调用状态更新器,因为它会继续调用 react 状态更新器,尽管它不会影响您的应用程序,因为如果再次向状态更新程序提供相同的状态,内部反应会阻止重新渲染。
const [message, setMessage] = useState({});
setMessage('my message');
return (
{message && (
<div>
<span>{message.text}</span>
// This on click makes the entire app reload
<button className='close' onClick={() => setMessage({})}>
X
</button>
</div>
)}
);
当您必须将消息传递给多个组件时,第二种更可靠的方法是为组件使用React.memo
const MyComponent = () => (
...
);
export default React.memo(MyComponent)
您应该将钩子定义为组件函数。 绑定变量,并且它setMessage
仅向该组件更新函数。 在 React 中,更新 dom 的唯一方法是调用React.Component
上的所有纯组件或render
函数,并将返回值与以前的返回进行比较。
因此,要在通过 react 更改视图后更新视图SetMessage
再次调用所有渲染函数来更新视图。
function MyComponet(){
return (
<div className='App'>
<Header user={user} message={'my message'} />
<div id='main-site'>
<Switch>
// SHOULD NOT RELOAD UNLESS PASSED IN PROP CHANGED
<Route path='/main' component={MainContent} />
</Switch>
</div>
</div>
);
}
//state that updating when props updating too
function usePropsState(initialState) {
const [state, setState] = useState(initialState);
useEffect(() => setState(initialState), [initialState]);
return [state, setState]
}
function Header({user, message:initMessage}){
// now you can update the state internally or from outside
const [message, setMessage] = usePropsState(initMessage);
return (
{message && (
<div>
<span>{message}</span>
// This on click makes the entire app reload
<button className='close' onClick={() => setMessage('')}>
X
</button>
</div>
)}
);
}
如果你喜欢那个自定义钩子 拇指 这个问题