我这里有这个函数,可以从pokeAPI获取数据,但我想将IsLoading状态设置为真,直到所有卡都渲染完毕.我下面所做的事情有时似乎有效,有时却无效.我是新手,所以我不太确定该问什么以及需要什么更多信息,所以请告诉我.

useEffect(() => {
  setIsLoading(true);
  async function fetchAllPokemonData() {
    try {
      if (search) {
        const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${search}`);
        const data = await res.json();
        setData([]);
        setData([data]);
      } else {
        for (let i = 0; i < pokemon.length; i++) {
          const res = await fetch(pokemon[i].url);
          const data = await res.json();
          setData((prev) => [...prev, data]);
          if (filter) {
            setData((data) => 
             data.filter((item) => 
               item.types.some((type) => 
                 type.type.name === filter)));
          }
        }
      }
    } catch (error) {
      console.log(error);
    } finally {
      setIsLoading(false);
    }
  }
  fetchAllPokemonData();
}, [pokemon, search, filter]);

try 使用try、catch和finally,但它有时有效,有时它只是立即或在没有生成所有卡时将isLoading设置回假.

推荐答案

没什么可看的. 然后不确定具体问题,如果你制作一个沙箱或一些东西来查看就容易多了.可以在Codesandbox或PlayCode上制作,甚至不需要在PlayCode上登录.

我要做的第一件事,我认为这通常是最佳实践,就是将提取与状态设置分开.它使做出更改变得更容易,尤其是在React中,您必须遵循hook规则.您可以在React文档上查找挂钩规则,我认为它解释得相当好.

在这种情况下,特别是有时您有条件地调用hook,这违反了hook的规则,因此它不会可靠地工作.

...
if (filter) {
  setData((data) => 
    data.filter((item) => 
...

for循环中也有对setData的调用,每次渲染时需要调用相同的次数.

因此,您可以进行许多更改,以便代码遵循挂钩规则.但一般来说,如果您考虑如何组织和拆分代码,您应该将代码置于可以更轻松满足挂钩规则或任何框架中的任何规则的位置.

在这里,在某些情况下,将神奇宝贝的获取与状态设置分开是有益的.所以您可以这样思考:您想要一个旨在根据某些输入获取一些数据的函数,并且理想情况下该函数始终以相同可靠的格式返回数据.在这种情况下,它可能是一个神奇宝贝数组,或者一个错误,或者一个神奇宝贝或错误的数组,或者一个仅代表成功获取的数组,或者其他事情,但这取决于你想要如何设计它.

不幸的是,在React中,您无法使用Deliverc效果函数args,因此您仍然需要在您创建的Deliverc函数中设置状态,这已经很棒了.但您仍然可以分离提取逻辑,并且您必须使挂钩工作.

重要的是您知道期望什么数据,并且在这里,在reaction的上下文中,任何条件逻辑都应该发生在状态设置器函数中.因此,在您的示例中,获取逻辑可能看起来像

async function fetchAllPokemonData() {
  async function getData() {
    let results = [];
    for (let i = 0; i < pokemon.length; i++) {
      const res = await fetch(pokemon[i].url)
        .catch((e) => console.log(e))
        .then((res) => {
          //any processing you want to do on result
          return res;
        });
    }
  }
  const data = getData();
  setData(data);
}

因此getData函数只是返回成功获取的神奇宝贝array.设置状态一次,set State函数将始终运行,无论获取的结果如何.

如果您想稍微简化代码,可以使用Promise.all之类的内容并创建一个获取promise array.这是一个细节但很好:

async function fetchAllPokemonData() {
  const data = await Promise.all(pokemon.map(p=>fetch(p.url)))
  setData(data);
}

然后,设置数据时,还可以设置isLoading个状态

setData(data);
setIsLoading(false);

Reactjs相关问答推荐

自动化幻灯片放映以防止React中重复过多的正确方法是什么

阻止在ShadCN和React中的FormLabel中添加 colored颜色

Shadck/ui Select -当用户 Select 项目时更改状态

Reaction Native:在初始获取后,Reducer变为未定义

react 下拉菜单任务

使用useReducer时,props 未从父级传递给子或孙级

如何通过回调函数获取多个值?

react 挂钩-使用有效澄清

GitHub页面未正确显示Reaction应用程序网站

取消 Select 较高组件中的所有行

在 React 中是否有任何理由要记住 Redux 操作创建者?

无法使用react-hook-form和react-places-autocomplete在字段中输入值

React 应用程序可以嵌入到 PowerPoint 中吗?

在 Nextjs13 应用程序目录中呈现从 supabase 获取的数据

使用 map 循环浏览列表列表中的列表并显示它们

如何使用react 路由将 url 参数限制为一组特定的值?

react-query、react-hook-form 和表单验证

如何防止 mui x-date-picker 被截断?

CORS 政策:无访问控制允许来源-AWS 和 Vercel

bootstrap 导航栏切换器在 reactjs 中不起作用