反应:将对象添加到状态数组

时间:2021-05-02 11:26:32

标签: javascript reactjs api axios

我正在尝试使用 forEach 循环将多个对象添加到状态数组:

const App = () => {
const [pokemon, setPokemon] = useState([]);
axios.get('https://pokeapi.co/api/v2/pokemon') // Gives me 20 pokemon
.then(res => {
  res.data.results.map(p => p.url).forEach(url => { // Loops over endpoints of pokemon
    axios.get(url)
    .then(response => {
      setPokemon(response.data)
    })
  });
})
}

正如您可能猜到的,当我 console.log pokemon 时,只显示 forEach 循环中的最后一项,因为它是在状态中设置的最后一项。

我正在使用的 API:https://pokeapi.co/

我从调用 https://pokeapi.co/api/v2/pokemon 开始,它给了我 20 个 pokemon,每个 pokemon 对象都带有一个端点以获取有关它的更多信息,我想将这些端点的信息作为对象存储在状态中.

感谢您的帮助,如果您知道更好的方法,请随时告诉我。

4 个答案:

答案 0 :(得分:1)

只需创建一个临时数组,将您从 API 获取的所有数据添加到该数组中,然后使用该变量设置状态。您不必每次都设置状态 - 您可以一次设置它。

const App = () => {
  const [pokemon, setPokemon] = useState([]);
  const tempArr = [];
  axios.get('https://pokeapi.co/api/v2/pokemon') // Gives me 20 pokemon
  .then(res => {
    res.data.results.map(p => p.url).forEach(url => { // Loops over endpoints of pokemon
      axios.get(url).then(response => {
        tempArr.push(response.data);
      })
    });
  });
  setPokemon(tempArr);
}

答案 1 :(得分:1)

我建议您在 Promise.all() 钩子内使用 useEffect()。通过使用 useEffect,您可以在组件挂载时(而不是每次渲染时)运行一次获取代码。使用 Promise.all() 允许您传递一个 promises 数组(这是 axios.get() 返回的内容),并将每个 Promise 解析为一个。这个 Promise 可以解析为每个 axios.get() 调用导致的一系列响应。这允许您只设置一次状态。

参见工作示例:

const {useState, useEffect} = React;
const App = () => {
  const [pokemon, setPokemon] = useState([]);
  
  useEffect(() => {
    axios.get('https://pokeapi.co/api/v2/pokemon')
      .then(res => Promise.all(res.data.results.map(pokemon => axios.get(pokemon.url))))
      .then(arr => setPokemon(arr.map(response => response.data)));
  }, []);
  
  return (<div>
    {pokemon.map(({id, species}) => <p key={id}>{species.name}</p>)}
  </div>);
}

ReactDOM.render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js" integrity="sha512-bZS47S7sPOxkjU/4Bt0zrhEtWx0y0CRkhEp8IckzK+ltifIIE9EMIMTuT/mEzoIMewUINruDBIR/jJnbguonqQ==" crossorigin="anonymous"></script>

答案 2 :(得分:0)

试试 setPokemon([...pokemon , response.data] )

答案 3 :(得分:0)

你可能应该使用

setPokemon (pokemon.concat(response.data)