Iterar a través de objetos anidados en React.js

Si alguna vez ha trabajado con API, sabrá que la estructura de los datos que devuelven puede complicarse rápidamente.

Imagina que llamas a una API desde tu proyecto React y la respuesta se parece a esto:

Object1 { Object2 { propertyIWantToAcess: anotherpropertyIWantToAcess: } }

Ha almacenado los datos dentro del estado de su componente como this.state.myPosts, y puede acceder a los elementos del objeto externo con lo siguiente:

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 }
    ); }

    Pero el problema es que no puede acceder a ninguno de los objetos internos.

    Los valores de los objetos internos siempre cambiarán, por lo que no podrá codificar sus claves e iterarlas para obtener los valores adecuados.

    Soluciones posibles

    Puede ser difícil trabajar directamente con respuestas API complejas, así que demos un paso atrás y simplifiquemos:

    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 lodashbiblioteca tiene métodos simples para lograr lo mismo, pero esta es una forma rápida y sucia de hacer lo mismo en Vanilla JS.

    Pero digamos que desea simplificar aún más, algo como:

    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} ); }

    Pero obtiene un error TypeError: can't convert undefined to object errorcada vez que intenta pasar postsa Object.keys.

    Tenga en cuenta que este error no tiene nada que ver con React. Es ilegal pasar un objeto como hijo de un componente.

    Object.keys()solo devuelve las claves del objeto que se pasa como parámetro. Deberá llamarlo varias veces para recorrer todas las claves anidadas.

    Si necesita mostrar todo el objeto anidado, una opción es usar una función para convertir cada objeto en un componente React y pasarlo como una matriz:

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

    {val}

    ) // wraps any non-object type inside

    }) ... return {data}

    Paquetes útiles

    Otra opción es usar un paquete como json-query para ayudar a iterar a través de los datos JSON anidados.

    Aquí hay una versión modificada de la renderfunción anterior usando 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} ); } }