J'ai un composant "home" avec des liens, et lorsque vous cliquez sur un lien, le composant est chargé avec le produit. J'ai aussi un autre composant qui est toujours visible, montrant des liens vers les "produits récemment visités".
Ces liens ne fonctionnent pas sur une page de produit. L'URL se met à jour lorsque je clique sur le lien et un rendu se produit, mais le composant du produit ne met pas à jour le nouveau produit.
Voir cet exemple: exemple de Codesandbox
Voici les itinéraires dans 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>;
Les liens dans ProductHistory ressemblent à ceci:
<Link to={`/products/${product.product_id}`}> {product.name}</Link>
Donc, ils correspondent à la Route path="/products/:product"
.
Lorsque je suis sur une page de produit et que je tente de suivre un lien ProductHistory, l'URL se met à jour et un rendu se produit, mais les données du composant ne changent pas. Dans l'exemple Codesandbox, vous pouvez supprimer le commentaire de l'alerte dans la fonction de rendu des composants du produit pour voir qu'elle s'affiche lorsque vous suivez le lien, mais rien ne se produit.
Je ne sais pas quel est le problème ... Pouvez-vous expliquer le problème et trouver une solution? Ce serait génial!
Avec componentDidMount
, vous devez également implémenter le componentWillReceiveProps
ou utiliser getDerivedStateFromProps
(à partir de la version 16.3.0) dans la page Products
car le même composant est re-rendered
avec les mises à jour params
et not re-mounted
lorsque vous modifiez les paramètres de route, cela est dû au fait que les paramètres sont transmis en tant qu’éléments au composant et que, lorsqu’ils changent d’accessoires, React les composants sont restitués et non montés à nouveau.
EDIT: à partir de v16.3.0, utilisez getDerivedStateFromProps
pour définir/mettre à jour l'état en fonction des accessoires (inutile de spécifiez-le dans deux méthodes de cycle de vie différentes)
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;
}
Avant la version 16.3.0, vous utiliseriez le composantWillReceiveProps
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
})
}
}
Comme le composant Produit est déjà chargé, il ne sera pas rechargé. Vous devez gérer un nouvel identifiant de produit dans la méthode de composant ci-dessous
componentWillReceiveProps(nextProps) {
if(nextProps.match.params.name.product == oldProductId){
return;
}else {
//fetchnewProduct and set state to reload
}
Avec la dernière version de react (à partir de 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
}
}
Bien que toutes les méthodes mentionnées ci-dessus fonctionnent, je ne vois pas pourquoi utiliser getDerivedStateFromProps
. Basé sur React docs, "si vous voulez recalculer certaines données uniquement lorsqu'un accessoire change, utilisez plutôt un assistant de mémorisation".
Ici, au lieu de cela, je suggérerais simplement d’utiliser componentDidUpdate
en changeant le Component
en PureComponenet
.
En faisant référence à React docs, PureComponenet
s uniquement restituer si au moins une valeur d'état ou prop change. Le changement est déterminé en effectuant une comparaison superficielle des clés d'état et 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
};
};
Veuillez noter que ce qui précède ne fonctionne que si vous modifiez le composant en PureComponent et, évidemment, vous devez l'importer à partir de React.
Si vous ne maintenez pas l'état de votre composant, vous pouvez utiliser componentDidUpdate
sans avoir besoin de getDerivedStateFromProps
:
componentDidUpdate(prevProps) {
const { match: { params: { value } } } = this.props
if (prevProps.match.params.value !== value){
doSomething(this.props.match.params.value)
}
}