我有一个" home"带链接的组件,当您单击链接时,产品组件随产品一起加载。我还有另一个始终可见的组件,显示了最近访问过的产品的链接"。
这些链接在产品页面上不起作用。单击链接时会更新URL,并且会进行渲染,但产品组件不会使用新产品进行更新。
查看此示例: Codesandbox example
以下是index.js中的路由:
<BrowserRouter>
<div>
<Route
exact
path="/"
render={props => <Home products={this.state.products} />}
/>
<Route path="/products/:product" render={props => <Product {...props} />} />
<Route path="/" render={() => <ProductHistory />} />
<Link to="/">to Home</Link>
</div>
</BrowserRouter>;
ProductHistory中的链接如下所示:
<Link to={`/products/${product.product_id}`}> {product.name}</Link>
所以它们匹配Route path="/products/:product"
。
当我在产品页面上并尝试关注ProductHistory链接时,会更新URL并进行渲染,但组件数据不会更改。在Codesandbox示例中,您可以取消注释Product components render function中的警报,以便在您按照链接时看到它呈现,但没有任何反应。
我不知道问题是什么......你能解释一下问题并找到解决方案吗?那太好了!
答案 0 :(得分:23)
与componentDidMount
一起,您还需要在componentWillReceiveProps
页面中实施getDerivedStateFromProps
或使用Products
(从v16.3.0开始),因为相同的组件是{{更改路径参数时更新re-rendered
和params
,这是因为params作为道具传递给组件并且在道具上更改,React组件重新渲染而不是重新安装。
编辑:使用getDerivedStateFromProps
根据道具设置/更新状态(无需在两种不同的生命周期方法中指定)
not re-mounted
在v16.3.0之前,您将使用componentWillReceiveProps
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.match.params.product !== prevState.currentProductId){
const currentProductId = nextProps.match.params.product
const result = productlist.products.filter(obj => {
return obj.id === currentProductId;
})
return {
product: result[0],
currentId: currentProductId,
result
}
}
return null;
}
<强> Working codesandbox 强>
答案 1 :(得分:5)
由于产品组件已加载,因此不会重新加载。您必须在以下组件方法
中处理新产品IDcomponentWillReceiveProps(nextProps) {
if(nextProps.match.params.name.product == oldProductId){
return;
}else {
//fetchnewProduct and set state to reload
}
最新版本的react(16.3.0起)
static getDerivedStateFromProps(nextProps, prevState){
if(nextProps.productID !== prevState.productID){
return { productID: nextProps.productID};
}
else {
return null;
}
}
componentDidUpdate(prevProps, prevState) {
if(prevProps.productID !== this.state.productID){
//fetchnewProduct and set state to reload
}
}
答案 2 :(得分:0)
如果您不维护组件的状态,则可以使用componentDidUpdate
而不需要getDerivedStateFromProps
:
componentDidUpdate(prevProps) {
const { match: { params: { value } } } = this.props
if (prevProps.match.params.value !== value){
doSomething(this.props.match.params.value)
}
}
答案 3 :(得分:0)
尽管上述所有方法都可以使用,但我看不出使用getDerivedStateFromProps
的意义。
根据React的文档,“如果只想在更改道具时才重新计算某些数据,请使用备忘录助手。”
在这里,我建议仅使用componentDidUpdate
并将Component
更改为PureComponenet
。
参考React文档,PureComponenet
仅在至少一个状态或prop值发生更改时才重新呈现。更改是通过对状态键和prop键进行比较来确定的。
componentDidUpdate = (prevProps) => {
if(this.props.match.params.id !== prevProps.match.params.id ) {
// fetch the new product based and set it to the state of the component
};
};
请注意,仅当您将Component更改为PureComponent时,上述方法才有效,并且显然,您需要从React导入它。