Iterar por meio de objetos aninhados em React.js
Se você já trabalhou com APIs, sabe que a estrutura dos dados que elas retornam pode se complicar rapidamente.
Imagine que você chame uma API de seu projeto React e a resposta seja mais ou menos assim:
Object1 { Object2 { propertyIWantToAcess: anotherpropertyIWantToAcess: } }
Você armazenou os dados no estado do seu componente como this.state.myPosts
e pode acessar os elementos do objeto externo com o seguinte:
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 }
); }
Mas o problema é que você não consegue acessar nenhum dos objetos internos.
Os valores dos objetos internos sempre mudarão, então você não pode codificar suas chaves e iterar por elas para obter os valores apropriados.
Soluções possíveis
Pode ser difícil trabalhar diretamente com respostas complexas de API, então vamos voltar um pouco e simplificar:
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 */
A lodash
biblioteca possui métodos simples para realizar a mesma coisa, mas esta é uma maneira rápida e suja de fazer a mesma coisa no vanilla JS.
Mas digamos que você queira simplificar ainda mais, 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} ); }
Mas você obtém um erro, TypeError: can't convert undefined to object error
sempre que tenta passar posts
para Object.keys
.
Lembre-se de que esse erro não tem nada a ver com React. É ilegal passar um objeto como filho de um componente.
Object.keys()
retorna apenas as chaves do objeto que é passado como parâmetro. Você precisará chamá-lo várias vezes para iterar por todas as chaves aninhadas.
Se você precisar exibir todo o objeto aninhado, uma opção é usar uma função para converter cada objeto em um componente React e passá-lo como uma matriz:
let data= [] visit(obj, (val) => { data.push(
{val}
) // wraps any non-object type inside
}) ... return {data}
Pacotes úteis
Outra opção é usar um pacote como json-query para ajudar a iterar pelos dados JSON aninhados.
Esta é uma versão modificada da render
função acima 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} ); } }