如何使用来自 API 的数据更新组件的状态

How to update state of the component with data from API

我对 React 和 useState 有疑问。

我正在尝试下载全部 characters from Star Wars API。我正在为此使用 Axios,因此此代码仅用于导入 Axios 实例:

import { instance } from 'api/getCharacters';

您可以在 代码示例 中看到我有一个运行 getCharacters 异步函数,它在第一次调用时下载 10 个字符,在所有下一次调用时下载 5 个字符(最后一次调用除外)。我将所有字符的 JSON 保存到 charactersArray。您还可以看到我正在将存储这些字符的状态变量传递给 CharactersList 组件。然后我只是映射字符数组,但这并不重要。我的问题是 - 如何使用 setCharacters 函数更新状态到之前的状态?我知道我应该这样做:

setCharacters([...characters, charactersArray])

你能告诉我如果我没有错并告诉我我应该在我的代码中的哪个地方执行上面的表达式吗?

代码示例:

import CharactersList from 'components/CharactersList/CharactersList';
import { Button } from 'components/Button/Button';
import { GlobalStyle } from 'styles/GlobalStyle';
import { Wrapper } from './Root.styles';
import { useState } from 'react';
import { instance } from 'api/getCharacters';

const Root = () => {
  const [characters, setCharacters] = useState([]);
  const charactersArray = [];
  const getCharacters = async () => {
    const loadedPeople = charactersArray.length;
    const maxPeople = 82;
    const perPage =
      loadedPeople === 80
        ? 2
        : loadedPeople >= maxPeople
        ? 0
        : loadedPeople < 10
        ? 10
        : 5;
    for (let index = loadedPeople; index < loadedPeople + perPage; index++) {
      const character = await instance.get(`${index + 1}`).catch((error) => {
        console.log(error);
        return error;
      });
      charactersArray.push(character.data);
    }
    console.log(charactersArray);
  };
  return (
    <Wrapper>
      <Button onClick={getCharacters}>Fetch</Button>
      <GlobalStyle />
      <CharactersList data={characters} />
    </Wrapper>
  );
};

export default Root;

谢谢

首先,遵循干净代码原则。

并且 instance 不是 API 命名空间的已知关键字。 例如:您可以使用 api().get('...')ApiCharachters.list()

I'm not sure about your async callback function. Read some articles before using it.

而且我认为这样会更好:

const MAX_PEOPLE = 82;

function calcPerPage(loaded) {
  if (loaded === 80) return 2;
  else if (loaded >= MAX_PEOPLE) return 0;

  return loaded < 10 ? 10 : 5;
}

const Root = () => {
  const [characters, setCharacters] = useState([]);

  const handleGetCharacters = async () => {
    const loadedPeople = characters.length;
    const perPage = calcPerPage(loadedPeople);

    for (let i = loadedPeople; i < loadedPeople + perPage; i++) {
      const character = await instance.get(`${i + 1}`).catch((error) => {
        console.log(error);
        return error;
      });

      setCharacters((prev) => [...prev, character]);
    }

    console.log(characters);
  };

  return (
    <Wrapper>
      <Button onClick={handleGetCharacters}>Fetch</Button>
      <GlobalStyle />
      <CharactersList data={characters} />
    </Wrapper>
  );
};