Dacă ați lucrat vreodată cu API-uri, veți ști că structura datelor pe care le returnează se poate complica rapid.

Imaginați-vă că apelați un API din proiectul dvs. React și răspunsul arată cam așa:

Object1 {
     Object2 {
           propertyIWantToAcess:
           anotherpropertyIWantToAcess:
      }
}

Ați stocat datele în starea componentei dvs. ca this.state.myPosts, și poate accesa elementele obiectului exterior cu următoarele:

render() {
    console.log(this.state.myPosts);

    const data = this.state.myPosts;

    const display = Object.keys(data).map((d, key) => {
    return (
      <div className="my-posts">
        <li key={key}>
          {data.current_route}
        </li>
      </div>
      );
    });

    return(
      <div>
        <ul>
          { display }
        </ul>
      </div>
    );
  }

Dar problema este că nu puteți accesa niciunul dintre obiectele interioare.

Valorile obiectelor interioare se vor schimba întotdeauna, deci nu puteți să le codificați cheile și să le repetați pentru a obține valorile corespunzătoare.

Solutii posibile

Poate fi dificil să lucrați direct cu răspunsuri API complexe, deci să facem un pas înapoi și să simplificăm:

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 biblioteca are metode simple pentru a realiza același lucru, dar acesta este un mod rapid și murdar de a face același lucru în vanilie JS.

Dar spuneți că doriți să simplificați în continuare, ceva de genul:

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 =>
      <option value={key}>{posts[key]}</option>
    )


    return(
      <div>
        {display}
      </div>
    );
 }

Dar primești o eroare, TypeError: can't convert undefined to object error ori de câte ori încercați să treceți posts la Object.keys.

Rețineți că această eroare nu are nicio legătură cu React. Este ilegal să treci un obiect ca copil al unei componente.

Object.keys() returnează doar cheile obiectului trecut ca parametru. Va trebui să-l apelați de mai multe ori pentru a itera prin toate tastele imbricate.

Dacă trebuie să afișați întregul obiect imbricat, o opțiune este să utilizați o funcție pentru a converti fiecare obiect într-o componentă React și a-l transmite ca o matrice:

let data= []

visit(obj, (val) => {
    data.push(<p>{val}</p>)  // wraps any non-object type inside <p>
})
...
return <SomeComponent> {data} </SomeComponent>

Pachete utile

O altă opțiune este utilizarea unui pachet de genul json-interogare pentru a ajuta la iterație prin datele JSON imbricate.

Iată o versiune modificată a render funcția de mai sus folosind json-query:

 render() {
   const utopian = Object.keys(this.state.utopianCash);
   console.log(this.state.utopianCash);

   var author = jsonQuery('[*]', { data: this.state.utopianCash }).value
   var title = jsonQuery('[*]Iterate Through Nested Object in React.js', { 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 (
       <div className="utopian-items">
        <p>
          <strong>Author: </strong>
          {author[i]}
        </p>
        <p>
          <strong>Title: </strong>
            <a href={`https://www.steemit.com` + postLink[i]}>{title[i]}</a>
        </p>
        <p>
          <strong>Pending Payout: </strong>
            {pendingPayout[i]}
        </p>
        <p>
          <strong>Votes: </strong>
          {netVotes[i]}
        </p>
       </div>
     );
   });

    return (
      <div className="utopian-container">
        {display}
        <User />
      </div>
    );
  }
}