Итерация чрез вложен обект в React.js

Ако някога сте работили с API, ще знаете, че структурата на данните, които връщат, може бързо да се усложни.

Представете си, че извиквате API от вашия проект React и отговорът изглежда по следния начин:

Object1 { Object2 { propertyIWantToAcess: anotherpropertyIWantToAcess: } }

Съхранили сте данните в състояние на вашия компонент като this.state.myPostsи можете да получите достъп до елементите на външния обект със следното:

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

    Но проблемът е, че нямате достъп до нито един от вътрешните обекти.

    Стойностите на вътрешните обекти винаги ще се променят, така че не можете да кодирате ключовете им и да прегледате тези, за да получите правилните стойности.

    Възможни решения

    Може да е трудно да работите директно със сложни API отговори, така че нека да направим крачка назад и да опростим:

    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 */

    В lodashбиблиотеката има прости методи, за да постигнете същото, но това е бърз и мръсен начин да направи същото нещо в ванилия JS.

    Но кажете, че искате да опростите допълнително, нещо като:

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

    Но получавате грешка TypeError: can't convert undefined to object errorвсеки път , когато се опитате да преминете postsкъм Object.keys.

    Имайте предвид, че тази грешка няма нищо общо с React. Незаконно е да се предава обект като дете на компонент.

    Object.keys()връща само ключовете на обекта, който е предаден като параметър. Ще трябва да го извикате няколко пъти, за да прегледате всички вложени ключове.

    Ако трябва да покажете целия вложен обект, една от опциите е да използвате функция за конвертиране на всеки обект в React компонент и да го предадете като масив:

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

    {val}

    ) // wraps any non-object type inside

    }) ... return {data}

    Полезни пакети

    Друга възможност е да използвате пакет като json-query, за да помогнете за итерация през вложените JSON данни.

    Ето модифицирана версия на renderфункцията по-горе, използвайки 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} ); } }