当我更改不相关的状态时,为什么我的所有组件都重新呈现?
Why are all my component rerendering when I change an unrelated state?
我正在尝试在不重新加载整个应用程序的情况下更改状态。由于某种原因,这并没有发生,当我设置一个甚至没有传递给特定组件的对象的状态时,该组件就会无缘无故地更新。
所以在下面的代码中,我在设置消息时,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>
);
Header.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
属性的组件得到更新,而没有其他组件重新渲染?
您应该将钩子定义到组件函数中。绑定变量,它 setMessage
仅更新函数到该组件。
在 React 中,更新 dom 的唯一方法是调用 React.Component
上的所有纯组件或 render
函数,并将 return 与之前的 return 进行比较。
因此,在通过 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>
)}
);
}
如果你喜欢那个自定义挂钩,请顶起this问题
有两种方法可以解决您的问题。
第一个涉及将您的状态向下移动到 Child 组件,即 Header,因为只有 Header 使用 message
状态。另一件要记住的事情是,你不要在渲染中直接调用状态更新器,因为它会继续调用反应状态更新器,尽管它不会影响你的应用程序,因为如果相同的状态是反应内部阻止 re-render再次提供给状态更新器。
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)
我正在尝试在不重新加载整个应用程序的情况下更改状态。由于某种原因,这并没有发生,当我设置一个甚至没有传递给特定组件的对象的状态时,该组件就会无缘无故地更新。
所以在下面的代码中,我在设置消息时,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>
);
Header.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
属性的组件得到更新,而没有其他组件重新渲染?
您应该将钩子定义到组件函数中。绑定变量,它 setMessage
仅更新函数到该组件。
在 React 中,更新 dom 的唯一方法是调用 React.Component
上的所有纯组件或 render
函数,并将 return 与之前的 return 进行比较。
因此,在通过 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>
)}
);
}
如果你喜欢那个自定义挂钩,请顶起this问题
有两种方法可以解决您的问题。
第一个涉及将您的状态向下移动到 Child 组件,即 Header,因为只有 Header 使用 message
状态。另一件要记住的事情是,你不要在渲染中直接调用状态更新器,因为它会继续调用反应状态更新器,尽管它不会影响你的应用程序,因为如果相同的状态是反应内部阻止 re-render再次提供给状态更新器。
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)