TLDR
是否有一种方法可以迫使React从头开始重新创建组件(使用钩子功能组件),而不是在prop
更改时重新呈现它?
编辑
键属性确实起作用。我遇到的问题是由于我正在执行的状态更新序列。第一次更新正在尝试立即呈现需要完成最后一次更新的组件。
我正在开发一个名为<AddProductWidget>
的组件,它将获得有关产品的以下props
信息,并且需要显示其详细信息。它属于带有搜索栏的页面,您需要输入产品ID并从云功能获取产品详细信息。
它呈现如下:
<AddProductWidget
userImages={props.productDetails.userImages} // Array of strings (urls)
title={props.productDetails.title}
stars={props.productDetails.stars}
/>
AddProductWidget.js
它呈现一个<UserImages>
组件,该组件使用户可以在保存到数据库之前单击一些图像进行选择。因此,它需要一个state
才能“记住”用户单击了哪些图像。
function AddProductWidget(props) {
const [userImagesSelected, setUserImagesSelected] = useState(
() => {
if (props.userImages && props.userImages > 0) {
return new Array(props.userImages.length).fill(false);
}
return null;
}
);
// IT renders the <UserImages> component
// The code here is simplified
return(
<UserImages
userImages={props.userImages}
userImagesSelected={userImagesSelected}
setUserImagesSelected={setUserImagesSelected}
/>
);
}
该数组userImagesSelected
的初始状态应与userImages
数组的长度相同,并用false
值填充,一旦用户开始,它将变为true
单击图像。如果产品没有用户图像,则props.userImages
将是null
,userImagesSelected
也应该是null
。
当我加载第一个产品时,一切都按预期工作。无论是否有图像,一切都可以正确显示。
问题:
问题是,例如,当我加载一个产品的图像为零时,随后又加载了另一个产品的图像为5个。基本上props
的{{1}}会发生变化(因为它收到了新产品),但是由于React似乎正在尝试使用相同的组件实例,所以我得到了一个错误,因为我的AddProductWidget
组件将尝试呈现选定的图像信息,但是UserImages
的状态仍为userImagesSelected
,因为最后的产品没有图像。
在使用类时,我可以强制React使用null
属性来重新创建组件实例,但这似乎不适用于钩子,因为以下代码无法解决我的问题:
key
问题
是否有一种方法可以迫使React从头开始重新创建组件(使用钩子功能组件),而不是在 <AddProductWidget
key={productID}
userImages={props.productDetails.userImages} // Array of strings (urls)
title={props.productDetails.title}
stars={props.productDetails.stars}
/>
更改时重新呈现它?
额外
A找到了解决方法,但是即使在React文档中,它似乎也有点怪异。它基本上使用状态来检测prop
何时更改,并在渲染期间调用props
。我希望从头开始重新创建组件。
答案 0 :(得分:2)
不确定您如何确定其他key
不会重新安装组件,但是应该这样做(您确定密钥已更改?)
这是一个正在运行的示例,显示了此
function Test() {
React.useEffect(() => {
console.log('Test was mounted');
return () => {
console.log('Test was un-mounted');
};
}, []);
return "hi there, I'm Test";
}
function App() {
const [val, setVal] = React.useState("Change me...");
return (
<div className="App">
<input value={val} onChange={e => setVal(e.target.value)} />
<br />
<Test key={val} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root" />