javascript - 在 setState 钩子中改变 prevState 更新视图而不重新渲染。为什么?
问题描述
我的 changeProductName 函数称为 setState,它返回一个“变异的 prevState”。我通过 ContextAPI 将函数传递给子组件并在子组件中调用它。该函数成功更新了子项和父项中显示的产品名称,但父项确实触发了重新渲染。父级如何在不重新渲染的情况下更新视图?谁能解释 setState 中的 prevState 实际上是什么?
const App = () => {
const [products, setProducts] = useState(initialValues);
const changeProductName = (id, newName) => {
setProducts((prevState) => { //is preState a copy of state?
prevState.products.filter(
(product) => product.id === id
)[0].name = newName; //Mutates prevState
return prevState; //Did I return a new state?
});
};
useEffect(() =>
console.log("I would know when App re-renders")); //No re-render!
return (
<> //Some React Switch and Routers
<div>
{product.map(product=>product.name)} //Successfully Updated!
</div>
<ProductContext value={(products, changeProductName)}>
<ProductPage /> //call changeProductName and it works!
</ProductContext>
</>
);
};
如果我更改了不触及 prevState 的函数,则父级会按预期重新渲染。这种方法更好吗?
//this will trigger parent re-render.
const changeProductName = (id, newName) => {
setProducts((prevState) => {
prevState.products.filter(
(product) => product.id === id
)[0].name = newName;
return prevState;
});
};
解决方案
据我所知,改变状态通常是一个坏主意。
根据这个答案,改变状态可能不会导致重新渲染,因为在突变期间对状态对象的引用没有改变。
我宁愿使用某种类似 redux 的不可变模式:
const changeProductName = (id, newName) => {
setProducts((prevState) => (
prevState.map(product=>{
if(product.id!==id){
// name is not changed since the id does not match
return product;
} else {
// change it in the case of match
return {...product, name:newName}
}
}
)
}
推荐阅读
- html - 在标记小说时,我应该使用多个 p 元素还是一个带有 br 元素的 p 元素?
- internet-explorer - 字体行高IE浏览器兼容性问题
- hibernate - 使用带有通用 Java 编程的 Quarkus Panache 实体时出错
- sql - 查找两行的相似百分比
- python - 如何检查列中所有值之间的范围
- mongoose - Mongoose TypeError: Rental 不是构造函数
- jmeter - JMeter CSV 一一运行
- python - python 字典列表,如何打印product_id,其中“停止”等于'1'?
- javascript - 如何为 100 个菜单项创建一个下拉菜单?
- .net - 在 Rider 中将 HostingEnvironment.EnvironmentName 设置为 Development