J'essaie de créer un composant dynamique qui correspond à l'index de données avec le paramètre d'URL blogID que j'obtiens avec le avec le routeur.
Ici, j'ai les paramètres du routeur et j'envoie les accessoires au composant
render(){
const { params:{ blogId, blogTitle } } = this.props.match;
// so i map here to get the index and set the conditional to set the new state but I don't know where or how exactly
this.props.blogData.map((val, idx) => (
idx == blogId ?
this.setState({blogData:val }) : null
))
return (
<div>
<BlogView title={this.state.blogData.title} />
</div>
)
}
puis sur le composant, je règle l'état initial et j'essaye de rendre les données qui correspondent à l'index des données, mais j'obtiens une erreur de composant appelant à plusieurs reprises setstate et des boucles infinies.
constructor(props){
super(props);
this.state = {
blogId:'',
blogTitle:'',
blogData:[]
}
}
<Route path='/blog/:blogId/:blogTitle' render={() => <BlogPost blogData={this.state.blogData} /> } />
5 Réponses :
Si vous appelez setState dans le rendu comme ceci, vous provoquerez des boucles infinies.
Vous n'avez pas besoin de setState une fois que vous avez trouvé le blog , utilisez simplement son titre dans BlogView après un find:
render() {
const { params:{ blogId, blogTitle } } = this.props.match;
const blog = this.props.blogData.find((val, idx) => idx === blogId);
return (
<div>
<BlogView title={blog.title} />
</div>
);
}
La raison pour laquelle vous obtenez une boucle infinie qui appelle un setState dans votre méthode de rendu, ce qui provoque un re-rendu, ce qui provoque un setState, qui provoque un re-rendu ... etc.
Essayez de retirer cette partie de la méthode de rendu.
this.props.blogData.map ((val, idx) => (
idx == blogId? this.setState ({blogData: val}): null))
Vous ne devriez pas définirState dans la fonction render (), la raison en est que lorsque vous définissez state, compoennt doit effectuer un nouveau rendu pour montrer à l'utilisateur les données mises à jour, puis le restituer encore et encore, à la place, faites-le dans componentDidMount lifeCycle méthode pour qu’elle ne s’exécute qu’une seule fois
componentDidMount() {
const { params:{ blogId, blogTitle } } = this.props.match;
this.props.blogData.map((val, idx) => (
idx == blogId ?
this.setState({blogData:val }) : null
))
}
Ajoutez un bloc conditionnel avant d'appeler l'état défini dans le rendu. si les deux valeurs sont identiques, n'appelez pas l'état défini.
render(){
const { params:{ blogId, blogTitle } } = this.props.match;
// so i map here to get the index and set the conditional to set the new state but I don't know where or how exactly
this.props.blogData.map((val, idx) => (
(idx == blogId && val != this.state.blogData) ?
this.setState({blogData:val }) : null
))
return (
<div>
<BlogView title={this.state.blogData.title} />
</div>
)
}
Oui je l'ai finalement fait,
J'ai défini l'état sur le componentDidMount ()
const blogger = this.props.blogData.map((val, idx) => (
idx == this.state.blogId ?
<BlogView
title={val.title}
body={parse(val.body)}
img={val.thumb}
/>
: null
))
et la comparaison sur le rendu et ça a fonctionné parfaitement
componentDidMount(){
const { params:{ blogId, blogTitle } } = this.props.match;
this.setState({blogId, blogTitle});
}