首页 > 解决方案 > 如何使用 API 中的数据更新组件的状态

问题描述

我对 React 和 useState 有疑问。

我正在尝试从 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;

谢谢

标签: javascriptreactjsreact-hooksuse-state

解决方案


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

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

我不确定您的异步回调函数。在使用它之前阅读一些文章。

我认为这样会更好:

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>
  );
};


推荐阅读