リンクのある「ホーム」コンポーネントがあり、リンクをクリックすると、製品コンポーネントに製品がロードされます。また、常に表示される別のコンポーネントもあり、「最近訪れた製品」へのリンクが表示されます。
これらのリンクは、製品ページでは機能しません。リンクをクリックすると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の例では、製品コンポーネントのレンダリング機能のアラートのコメントを解除して、リンクをたどったときにレンダリングされることを確認できますが、何も起こりません。
問題が何なのかわかりません...問題を説明して解決策を見つけることができますか?それは素晴らしいことです!
componentDidMount
に加えて、componentWillReceiveProps
を実装するか、getDerivedStateFromProps
ページでProducts
(v16.3.0以降)を使用する必要もあります。これは、同じコンポーネントがre-rendered
であり、更新されたparams
とnot re-mounted
これは、パラメーターが小道具としてコンポーネントに渡され、小道具が変更されると、Reactコンポーネントが再レンダリングされ、再マウントされないためです。
EDIT:v16.3.0から getDerivedStateFromProps
を使用して、propsに基づいて状態を設定/更新します(2種類で指定する必要はありません)ライフサイクルメソッド)
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;
}
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
})
}
}
製品コンポーネントはすでにロードされているため、リロードされません。コンポーネントの以下のメソッドで新しい製品IDを処理する必要があります
componentWillReceiveProps(nextProps) {
if(nextProps.match.params.name.product == oldProductId){
return;
}else {
//fetchnewProduct and set state to reload
}
反応の最新バージョン(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
}
}
上記の方法はすべて機能しますが、getDerivedStateFromProps
を使用するポイントは見当たりません。 Reactドキュメントに基づいて、「プロップが変更されたときにのみ一部のデータを再計算する場合は、代わりにメモ化ヘルパーを使用します」。
ここでは、代わりに、componentDidUpdate
をComponent
に変更して、PureComponenet
を使用することをお勧めします。
React docsを参照すると、PureComponenet
sは、少なくとも1つの状態またはプロップ値が変更された場合にのみレンダリングします。変更は、状態キーとプロップキーの浅い比較を行うことで決定されます。
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
};
};
上記は、コンポーネントをPureComponentに変更した場合にのみ機能し、明らかに、Reactからインポートする必要があることに注意してください。
コンポーネントの状態を維持していない場合は、componentDidUpdate
を使用せずにgetDerivedStateFromProps
を使用できます。
componentDidUpdate(prevProps) {
const { match: { params: { value } } } = this.props
if (prevProps.match.params.value !== value){
doSomething(this.props.match.params.value)
}
}