Problems traversing Javascript object

Asked

Viewed 91 times

2

I am consuming an API and displaying data with React. The API returns the following Json:

{
    "1": {
        "id": 1,
        "nome": "Outros",
        "abreviacao": "OUT",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Outros"
    },
    "1349": {
        "id": 1349,
        "nome": "Ipatinga",
        "abreviacao": "IPA",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Ipatinga"
    },
    "1371": {
        "id": 1371,
        "nome": "Cuiabá",
        "abreviacao": "CUI",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Cuiabá"
    },
    "1390": {
        "id": 1390,
        "nome": "Icasa",
        "abreviacao": "ICA",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Icasa"
    },
    "2190": {
        "id": 2190,
        "nome": "Oeste",
        "abreviacao": "OES",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Oeste"
    },
    "2193": {
        "id": 2193,
        "nome": "Duque de Caxias",
        "abreviacao": "DUQ",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Duque de Caxias"
    },
    "2197": {
        "id": 2197,
        "nome": "Americana",
        "abreviacao": "AME",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Americana"
    },
    "2554": {
        "id": 2554,
        "nome": "Grêmio Prudente",
        "abreviacao": "PRU",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Grêmio Prudente"
    },
    "2565": {
        "id": 2565,
        "nome": "Luverdense",
        "abreviacao": "LUV",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Luverdense"
    }

}

I would like to display this data in a table, but when trying to go through with map, I have an error:

TypeError: times.map is not a function

Follow the script in JS:

class App extends Component{

  state = {
    times: [],
  }

  async componentDidMount(){
    const response = await api.get('')
    this.setState({times: response.data})
    console.log(response.data)
  }
  render(){
    const {times} = this.state
    return(
      <div>
        {times.map(time =>(
          <li key={time.id}>
            {time.id}
          </li>
        ))}
      </div>
    )
  }
}

2 answers

1

What you are getting from your API is not an array, it is an object that is indexing the teams by their ids.

Like map is a method of objects of the type array, there is no way to invoke it on the object you received as a response from your API.

To handle this, you can convert the object into an array, or keep it as an object and iterate over its properties.

Example of how to handle this case by converting the object into an array:

async componentDidMount(){
  const response = await api.get('')
  this.setState({ times: Object.values(response.data) })
}

0


Your JSON is an object where each key of this object also represents another object, quite different than interacting on one array of objects that with the map is easy, but how to solve this problem you must first identify each key of this object with Object.Keys() returning only the keys, and after that it is easy to go through each item of that object and rescue its values, example:

function App() {
  const data = {
    "1": {
        "id": 1,
        "nome": "Outros",
        "abreviacao": "OUT",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Outros"
    },
    "1349": {
        "id": 1349,
        "nome": "Ipatinga",
        "abreviacao": "IPA",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Ipatinga"
    },
    "1371": {
        "id": 1371,
        "nome": "Cuiabá",
        "abreviacao": "CUI",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Cuiabá"
    },
    "1390": {
        "id": 1390,
        "nome": "Icasa",
        "abreviacao": "ICA",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Icasa"
    },
    "2190": {
        "id": 2190,
        "nome": "Oeste",
        "abreviacao": "OES",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Oeste"
    },
    "2193": {
        "id": 2193,
        "nome": "Duque de Caxias",
        "abreviacao": "DUQ",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Duque de Caxias"
    },
    "2197": {
        "id": 2197,
        "nome": "Americana",
        "abreviacao": "AME",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Americana"
    },
    "2554": {
        "id": 2554,
        "nome": "Grêmio Prudente",
        "abreviacao": "PRU",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Grêmio Prudente"
    },
    "2565": {
        "id": 2565,
        "nome": "Luverdense",
        "abreviacao": "LUV",
        "escudos": {
            "60x60": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_65x65.png",
            "45x45": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_45x45.png",
            "30x30": "https://s.glbimg.com/es/sde/f/organizacoes/escudo_default_30x30.png"
        },
        "nome_fantasia": "Luverdense"
    }

  };
  function loadObjectItems() {  
    return (
      <div>
        {Object.keys(data).map(time => (
          <li key={data[time].id} style={{listStyleType:'none'}}>
            <img src={data[time].escudos['30x30']} border="0" />
            {data[time].id} - {data[time].nome}
          </li>
        ))}
      </div>
    )
  }
  return (
    <div>{loadObjectItems()}</div>
  )
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

the main code to answer your question is:

<div>
    {Object.keys(data).map(time => (
      <li key={data[time].id}>
        {data[time].id} - {data[time].nome}
      </li>
    ))}
 </div>

where the Object.Keys() brings the keys of other objects and with this information can be mapped and rescue each object with its information and finishing to show the information as in the complete example.

The @user140828 response is a direct response and shows that you don’t need to change anything in your code, just how to put the state of a array, but, wanted to bring this solution so that really understand what happens and also another way to solve.

  • 1

    Great, helped me a lot to understand, thank you Virgilio.

  • negative votes started again to haunt stackoverflow, apart from the other problems already cited ..,

  • Virgilio, is there another endpoint in this same API that returns the object, as you would in this case? { "athletes": [], "esquema_id": 0, "current rotated": 1, "patrimonio": 0, "valor_time": 0, "capitao_id": null, "points": null, "pontos_campeonato": null, "time": { "subscriber": false, "full registration": true, "simplified": false, "clube_id": 264, "esquema_id": 1, "typo_adornment": 2, "typo_shirt": 1, "typo_shield": 1, "temporada_initial": 2016 } }

  • So, you can do the same thing that was passed on in the answer that you accepted, so it was easier for you to understand the initial problem of your question besides when you have other doubt should be generated another question, makes this generates another question @Adrianovalentim so you have more people to answer, the logic is the same, and you there in the comment not posted what is your doubt!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.