反应 useState 钩子不使用 axios 调用更新

Posted

技术标签:

【中文标题】反应 useState 钩子不使用 axios 调用更新【英文标题】:React useState hook not updating with axios call 【发布时间】:2021-10-20 04:18:58 【问题描述】:

我知道这是一个常见问题,因为我在过去的两个小时里都在检查每个答案并试图更新我的状态,但没有任何效果。

我正在从 cms 获取文本,但是在第一次加载时状态未定义并且我的应用程序崩溃了。但是,如果我注释掉该行,加载页面并取消注释该行会显示正确的值。

这是我尝试过的一些代码。

我希望得到的数据

[
  id:1,
  id:2,
  id:3,
  id:4,
]
import react, useEffect, useState from 'react'
import axios from 'axios'

const [carouselTitle, setCarouselTitle] = useState([])

useEffect(() => 
          fetchData();
    , []);


    const fetchData = async () => 
        await axios('api').then(
            response => 
                console.log(response.data)
                setCarouselTitle(response.data)
                console.log(carouselTitle)
            )
      ;
return(
  <h1>carouselTitle[1].id</h1>
)

控制台记录数据工作正常,但是当我控制台记录状态时它不起作用。

我尝试的第二种方法

    useEffect(() => 
        const fetchData = async () => 
         const res = await axios('api');
         const carouselTitleAlt = await res.data;
         setCarouselTitle( carouselTitleAlt );
         console.log(carouselTitleAlt);
         console.log(carouselTitle);
       ;
       fetchData();
      , []);

再次控制台记录 useEffect 中的 const 会显示正确的信息,但记录状态不起作用。

感谢您的回复或显示数据的更好方式。

【问题讨论】:

你在 useEffect 之外尝试过console.log(carouselTitle) 吗? const [carouselTitle, setCarouselTitle] = useState([] - 这是一个错字吗?缺少正确的括号? @selbie 是的,抱歉,这是一个 *** 错字可以确认我的代码有正确的括号!好地方寿:) @matt_roki2 的回答对你有帮助吗? 【参考方案1】:

setState 是异步的:https://reactjs.org/docs/faq-state.html#why-doesnt-react-update-thisstate-synchronously

这意味着您不能期望在调用setCarouselTitle 之后的行中控制台记录新的状态值。

要记录新值,您可以使用另一个 useEffect,在依赖项数组中使用 carouselTitle,您可以在其中 console.log(carouselTitle)

useEffect(() => 
  console.log(carouselTitle);
, [carouselTitle]);

也就是说,你的组件应该正确运行,当状态更新时它会被刷新。

在 JSX 中,您应该检查 carouselTitle 是否未定义(意味着请求失败或仍在等待中):

carouselTitle && <H1>carouselTitle[0].id

https://reactjs.org/docs/conditional-rendering.html#gatsby-focus-wrapper

【讨论】:

感谢您的回答。是的,这确实 console.log 它但仍然导致应用程序在页面刷新时以cannot read property of id 崩溃。如果它是状态更新,它可以工作,但仍然会遇到同样的问题...... :( 好的,具体的错误是什么?无法读取未定义的属性 ID?您如何尝试使用您获取的数据? 抱歉没有在您的回答中看到 JSX! 您应该在使用前检查 carouselTitle:carouselTitle && carouselTitle[1].id。编辑了我的答案。 和我问丹尼尔的问题一样,为什么会这样?【参考方案2】:

首先,如果将初始数据的空数组传递给 useState,则无法在此处获取该数组中的任何项:

return(
  <h1>carouselTitle[1].id</h1>
)

因为组件返回的数组的第一项没有任何内容。我更喜欢你这样做:

return(
  <h1>carouselTitle.length > 0 && carouselTitle[0].id</h1>
)

并且还基于this 和official documentation,setState(以及使用useState()setSomthing())是异步的。

所以状态数据在设置后不会立即显示。

【讨论】:

这已经解决了,谢谢,但是为什么呢?那行代码背后的逻辑是什么? 在您的版本中,您尝试访问一个未定义值的索引,直到请求返回。所以 javascript 会抛出一个错误。 @matt_roki2 正如我所说,您将一个空数组传递给useState,在第一次渲染中,组件返回一个没有任何内容的数组的第一项【参考方案3】:

你应该触发 useEffect 来运行 fetch 函数

useEffect(()=>fetchData();,[carouselTitle])

【讨论】:

以上是关于反应 useState 钩子不使用 axios 调用更新的主要内容,如果未能解决你的问题,请参考以下文章

反应钩子 useState 不使用 onSubmit 更新

如何在反应中使用带有useState钩子的回调[重复]

在 useState 钩子中反应设置状态

反应useState钩子,用函数调用setState [重复]

反应钩子useState()的真正奇怪的行为

在自定义反应钩子中使用 axios