Itérer à travers un objet imbriqué dans React.js

Si vous avez déjà travaillé avec des API, vous saurez que la structure des données qu'elles renvoient peut se compliquer rapidement.

Imaginez que vous appelez une API à partir de votre projet React et que la réponse ressemble à ceci:

Object1 { Object2 { propertyIWantToAcess: anotherpropertyIWantToAcess: } }

Vous avez stocké les données dans l'état de votre composant en tant que this.state.myPostset pouvez accéder aux éléments de l'objet externe avec les éléments suivants:

render() { console.log(this.state.myPosts); const data = this.state.myPosts; const display = Object.keys(data).map((d, key) => { return ( 
  • {data.current_route}
  • ); }); return(
      { display }
    ); }

    Mais le problème est que vous ne pouvez accéder à aucun des objets internes.

    Les valeurs des objets internes changeront toujours, vous ne pourrez donc pas coder en dur leurs clés et les parcourir pour obtenir les valeurs appropriées.

    Solutions possibles

    Il peut être difficile de travailler directement avec des réponses d'API complexes, alors prenons du recul et simplifions:

    const visit = (obj, fn) => { const values = Object.values(obj) values.forEach(val => val && typeof val === "object" ? visit(val, fn) : fn(val)) } // Quick test const print = (val) => console.log(val) const person = { name: { first: "John", last: "Doe" }, age: 15, secret: { secret2: { secret3: { val: "I ate your cookie" } } } } visit(person, print) /* Output John Doe 15 I ate your cookie */

    La lodashbibliothèque a des méthodes simples pour accomplir la même chose, mais c'est un moyen rapide et sale de faire la même chose dans vanilla JS.

    Mais disons que vous voulez simplifier davantage, quelque chose comme:

    render() { // Logs data console.log(this.state.myPosts); const data = this.state.myPosts; // Stores nested object I want to access in posts variable const posts = data.content; // Successfully logs nested object I want to access console.log(posts); // Error, this will not allow me to pass posts variable to Object.keys const display = Object.keys(posts).map(key => {posts[key]} ) return( {display} ); }

    Mais vous obtenez une erreur TypeError: can't convert undefined to object errorchaque fois que vous essayez de passer postsà Object.keys.

    Gardez à l'esprit que cette erreur n'a rien à voir avec React. Il est illégal de passer un objet en tant qu'enfant d'un composant.

    Object.keys()renvoie uniquement les clés de l'objet qui est passé en paramètre. Vous devrez l'appeler plusieurs fois pour parcourir toutes les clés imbriquées.

    Si vous avez besoin d'afficher tout l'objet imbriqué, une option consiste à utiliser une fonction pour convertir chaque objet en un composant React et le transmettre sous forme de tableau:

    let data= [] visit(obj, (val) => { data.push(

    {val}

    ) // wraps any non-object type inside

    }) ... return {data}

    Forfaits utiles

    Une autre option consiste à utiliser un package tel que json-query pour aider à parcourir les données JSON imbriquées.

    Voici une version modifiée de la renderfonction ci-dessus en utilisant json-query:

     render() { const utopian = Object.keys(this.state.utopianCash); console.log(this.state.utopianCash); var author = jsonQuery('[*][author]', { data: this.state.utopianCash }).value var title = jsonQuery('[*][title]', { data: this.state.utopianCash }).value var payout = jsonQuery('[*][total_payout_value]', { data: this.state.utopianCash }).value var postLink = jsonQuery('[*][url]', { data: this.state.utopianCash }).value var pendingPayout = jsonQuery('[*][pending_payout_value]', { data: this.state.utopianCash }).value var netVotes = jsonQuery('[*][net_votes]', { data: this.state.utopianCash }).value let display = utopian.map((post, i) => { return ( 

    Author: {author[i]}

    Title: {title[i]}

    Pending Payout: {pendingPayout[i]}

    Votes: {netVotes[i]}

    ); }); return ( {display} ); } }