【发布时间】:2018-06-18 00:39:16
【问题描述】:
当 url 参数发生变化时,我需要更新两个组件,但其中一个组件在带有参数的路由之外。 App.js 中的路由是这样的:
<BrowserRouter>
<div>
<Route exact path="/" render={ (props) =>
<Home products={this.state.products} }
/>
<Route path="/products/:product" render={ (props) =>
<Product {...props} /> }
/>
<Route path="/" render={ props =>
<ProductHistory {...props}/> }
/>
</div>
</BrowserRouter>
始终可见的 ProductHistory 具有指向产品的链接,例如:
<Link to={`/products/${product.product_id}`}> {product.name}</Link>
当关注这样的链接时,使用 ComponentWillReceiveProps 方法更新 Product 组件:
componentWillReceiveProps(nextProps) {
if(nextProps.match.params.product !== this.props.match.params.product){
但是如何在产品参数更改的同时更新 ProductHistory 组件?由于它不在 /products/:product 路由内,因此在 ProductHistory 的 componentWillReceiveProps 中检查 this.props.match.params.product 会得到 undefined。
(edit - withRouter 也无济于事,因为它已经在一个路由中,但是另一个路由:“/”)
在 componentWillReceiveProps 中我可以使用location.pathname 来检查路径是否以“/product”开头,我可以通过substr(path.lastIndexOf('/') + 1 找到参数。
编辑:但我还必须将当前 id 参数与下一个产品 id 参数进行比较,以避免不必要的更新。但是当点击链接时,当 componentWillReceiveProps 触发时,url 已经改变,所以location.pathname 和nextProps.location.pathname 总是匹配,所以它会不必要地更新(重复的 api 调用)。
所以我必须找到不同的解决方案 - 以某种方式重新安排路由?这个想法是 ProductHistory 应该始终可见。
【问题讨论】:
-
为什么不把
ProductHistory组件放在Product下面呢?为什么你需要为他们单独的路线? -
但是它只会显示在产品页面上,所以我必须复制它并将其放在其他路线上,我认为这会导致问题。
-
如果你的
ProductHistory依赖于:product_id,那么它就属于那里。如果用户导航到/blah,ProductHistory的内容是什么? -
产品历史记录显示访问过的产品(存储在会话中),因此每次访问产品时,都需要使用该产品更新历史记录。任何其他页面只会显示存储的产品历史记录。
-
将状态列表到包含
Product和ProductHistory组件的父组件中。在父级上使用状态并将父级的setState回调传递给Product页面,并在componentDidMount上使用正确的产品数据调用它。将父级的状态传递给ProductHistory以呈现列表。在父组件的 render 方法中使用来自 react router 的Switch。