【问题标题】:Fetching data in React's useEffect() returns "undefined"在 React 的 useEffect() 中获取数据返回“未定义”
【发布时间】:2020-03-15 00:11:27
【问题描述】:

我正在尝试从数据库中获取数据。这是一个获取请求。只要我在异步函数中使用获取的数据,一切正常。但除此之外,它只返回“未定义”。 我究竟做错了什么? 感谢您的帮助:)

const [accountInfos, setAccountInfos] = useState();
      const [error, setError] = useState();
      const [loading, setLoading] = useState(true);

      useEffect(() => {
        (async function runEffect() {
            const fetchedAccountInfos =  await fetchAccountInfos();
            if (fetchedAccountInfos && fetchedAccountInfos.length > 0) {
                console.log(fetchedAccountInfos)  //This console.log works
                setAccountInfos(fetchedAccountInfos);
                setLoading(false);
                console.log(accountInfos)  //This console.log returns 
                                             "undefined"
              } else {
                setError("Accountdaten können nicht geladen werden!");
                setLoading(false);
                };
        })();
      }, []);
      console.log(accountInfos);  //This console.log returns "undefined"

【问题讨论】:

  • accountInfos 是异步设置的,因此您不能指望它稍后再设置(在您 await 获取数据的范围之外)。您的代码需要测试数据是否存在。

标签: javascript reactjs promise use-effect react-functional-component


【解决方案1】:

它不是特定于 React 的:这是一个异步函数,所以在控制台日志发生后,promise 将得到解决,这就是你得到undefined 的原因。这只是正常的 JS 行为——在 console.log 执行时值 is 未定义。

在定义 JSX 的返回值中,如果accountinfos 为 null,则渲染 null(或某些空状态组件),否则根据 API 的返回值渲染实际组件。收到响应后,状态将更新,组件将重新渲染

【讨论】:

    【解决方案2】:

    你没有做错什么,useEffect 之外的 console.log 只是在初始组件函数调用上执行一次,所以当时 accountInfos 变量仍然未定义。

    不过useEffect里面的console.log是在获取数据后执行的,所以是当时定义的。

    【讨论】:

      【解决方案3】:

      试试这个只是为了看看结果?

            const [accountInfos, setAccountInfos] = useState();
            const [error, setError] = useState();
            const [loading, setLoading] = useState(true);
      
            useEffect(() => {
              (async function runEffect() {
                  const fetchedAccountInfos =  await fetchAccountInfos();
                  if (fetchedAccountInfos && fetchedAccountInfos.length > 0) {
                      setAccountInfos(fetchedAccountInfos);
                      setLoading(false);
                      console.log(accountInfos)  //This console.log works
                    } else {
                      setError("Accountdaten können nicht geladen werden!");
                      setLoading(false);
                      };
              })();
            }, []);
            console.log(accountInfos);  //This console.log returns "undefined"
      
            useEffect(() => {
              console.log(accountInfos); //check the result here
            }, [accountInfos])
      

      【讨论】:

      • 但还是尝试了你的建议。首先它还返回“未定义”,然后它返回正确的对象。所以它会触发两次
      • 但我现在真的不知道如何处理这些信息。
      • 您从该获取中获得的数据可能会显示在 JSX 中的某个位置,该位置位于 return();所以你在那里不会遇到任何问题。至于你的情况,我认为 Daniel Herrero Hernando 给了你正确的答案。
      【解决方案4】:

      由于大多数答案已经说明了问题的原因,即 JS 的异步性质。 解决这个问题的解决方案是简单地使用条件语句或三元运算符。

      const [accountInfos, setAccountInfos] = useState();
        const [error, setError] = useState();
        const [loading, setLoading] = useState(true);
      
        useEffect(() => {
          (async function runEffect() {
              const fetchedAccountInfos =  await fetchAccountInfos();
              if (fetchedAccountInfos && fetchedAccountInfos.length > 0) {
                  console.log(fetchedAccountInfos)  //This console.log works
                  setAccountInfos(fetchedAccountInfos);
                  setLoading(false);
                  if(accountInfos){
                      //console the output only if available
                       console.log(accountInfos);
                  }
                } else {
                  setError("Accountdaten können nicht geladen werden!");
                  setLoading(false);
                  };
          })();
        }, []);
        console.log(accountInfos);  //This console.log returns "undefined"
      

      如果渲染组件并在 useEffect 钩子中获取一些数据,同样的方法很有用。

      {
         dataIsReturned ? <RenderYourData/> : <h1> Loading </h1>
      }
      

      【讨论】:

        【解决方案5】:

        为了获取更新后的值,然后根据该值执行一些操作,您需要使用useEffect 挂钩

        例如

        const [toggle, setToggle] = useState(false);
        
        useEffect(() => {
           // do something based on new value of toggle
        }, [toggle]);
        
        const trigger = () => {
          setToggle(true);
          // OR
          //setToggle(t => !t);
        }

        【讨论】:

        • 这个问题实际上是关于在useEffect 中获取数据,它在问题标题中,代码在问题正文中。这是对不同问题的回答吗(您的回答似乎与这里的任何内容无关)?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-01
        • 2022-12-05
        • 2020-09-26
        • 1970-01-01
        • 2021-10-28
        • 2020-07-12
        • 1970-01-01
        相关资源
        最近更新 更多