Javascript 反应不';t在路由参数更改或查询更改时重新加载组件数据

Javascript 反应不';t在路由参数更改或查询更改时重新加载组件数据,javascript,reactjs,react-router,react-router-v4,react-router-dom,Javascript,Reactjs,React Router,React Router V4,React Router Dom,我有一个带有链接的“主页”组件,当您单击链接时,产品组件将与产品一起加载。我还有一个始终可见的组件,显示“最近访问的产品”的链接 这些链接在产品页面上不起作用。当我单击链接时,url会更新,并进行渲染,但产品组件不会随新产品更新 请参见此示例: 以下是index.js中的路由: <BrowserRouter> <div> <Route exact path="/" render={props => <Ho

我有一个带有链接的“主页”组件,当您单击链接时,产品组件将与产品一起加载。我还有一个始终可见的组件,显示“最近访问的产品”的链接

这些链接在产品页面上不起作用。当我单击链接时,url会更新,并进行渲染,但产品组件不会随新产品更新

请参见此示例:

以下是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>
{product.name}
因此它们与
路径=“/products/:product”
匹配

当我在产品页面上并尝试跟踪ProductHistory链接时,URL会更新并呈现,但组件数据不会更改。在Codesandbox示例中,您可以取消对Product components render函数中的警报的注释,以查看它在跟随链接时的渲染情况,但什么也没有发生


我不知道问题是什么……你能解释一下问题并找到解决办法吗?那太好了

由于产品组件已加载,因此不会重新加载。您必须使用下面的组件方法处理新产品id

componentWillReceiveProps(nextProps) {
if(nextProps.match.params.name.product == oldProductId){
  return;
}else {
 //fetchnewProduct and set state to reload
}
使用最新版本的react(16.3.0及以后版本)


除了
componentDidMount
,您还需要实现
componentWillReceiveProps
或使用
getDerivedStateFromProps
(从v16.3.0开始)在
Products
页面中,由于使用更新的
params
未重新安装
重新呈现相同组件,因此当您更改路由参数时,这是因为params作为道具传递给组件,并且在道具更改时,React组件重新呈现而未重新安装

编辑:来自v16.3.0,用于根据道具设置/更新状态(无需在两种不同的生命周期方法中指定)

在v16.3.0之前,您将使用componentWillReceiveProps

componentWillReceiveProps(nextProps) {
    if (nextProps.match.params.product !== this.props.match.params.product) {
      const currentProductId = nextProps.match.params.product
      const result = productlist.products.filter(obj => {

        return obj.id === currentProductId;

      })
      this.setState({

        product: result[0],
        currentId: currentProductId,
        result

      })
    }
  }

如果您不在组件中维护状态,则可以使用
componentdiddupdate
,而无需
getDerivedStateFromProps

componentDidUpdate(prevProps){
const{match:{params:{value}}}=this.props
if(prevProps.match.params.value!==值){
doSomething(this.props.match.params.value)
}
}

尽管上述所有方法都有效,但我认为使用
getDerivedStateFromProps
没有任何意义。 根据React文档,“如果您只想在道具更改时重新计算某些数据,请改用备忘录辅助工具”

在这里,我建议只使用
componentdiddupdate
,同时将
组件更改为
PureComponenet

对于React文档,
PureComponenet
s仅在至少一个状态或属性值发生变化时才重新提交。通过对状态键和道具键进行粗略比较来确定更改

componentDidUpdate=(prevProps)=>{
if(this.props.match.params.id!==prevProps.match.params.id){
//基于获取新产品并将其设置为组件的状态
};

};组件WillReceiveProps现在已不推荐使用。但是你还能怎么做呢?@BastianVoigt:你可以在react+16.3
getDerivedStateFromProps
componentdiddupdate
中使用新生命周期方法的集成,如中所述。我尝试了
getDerivedStateFromProps
解决方案。但它不起作用。似乎
getDerivedStateFromProps
仅在装载时触发一次。@arvinsim,不是真的,getDerivedStateFromProps在初始装载时以及在每次其他更新时都会触发。16.4版本中的API也发生了变化。我将更新我的答案,以纳入这一变化。这为我指明了正确的方向,感谢您的伟大回答。ComponentWillReceiveProps现在也被弃用并被认为是不安全的。。。还有其他方法吗?@BastianVoigt应该是prevProps,因为在props更改后将调用componentDidUpdate,这与我们在getDerivedStateFromProps中设置的下一步相同。对,但我希望在当前productID(this.props.productID)与我所在状态不同时重新加载,“你不这么认为吗?”巴斯蒂安沃伊特。对,这就是上述条件的作用。当前productID(this.props.producID)将有新的productID,我们在state变量中已经说过了。如果我们比较这一点,那么在我的情况下,它也适用于常规组件。在没有
PureComponent
的情况下,它也适用于我,谢谢!
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;
}
componentWillReceiveProps(nextProps) {
    if (nextProps.match.params.product !== this.props.match.params.product) {
      const currentProductId = nextProps.match.params.product
      const result = productlist.products.filter(obj => {

        return obj.id === currentProductId;

      })
      this.setState({

        product: result[0],
        currentId: currentProductId,
        result

      })
    }
  }