首页 > 解决方案 > 即使“then”返回值响应,useEffect 也返回未定义

问题描述

我似乎无法弄清楚为什么 useEffect 会这样做...... Wait() 是一个睡眠异步函数, getData() 是一个 Axios 请求。

        return wait().then(getData().then((resp) => {
            console.log(resp)
        }))

此代码记录了 resp 变量的有效值,但它在 return 语句中返回 undefined。发生了什么,我如何让它返回 resp 变量?

编辑***

const wait = React.useCallback( async() => {
    if (loading === false) {
        await sleep(4000);
    } else if (loading === true){
        await sleep(0);
    } else {
        await sleep(2000);
    }
}, [loading])

const getData = React.useCallback(() => {
    const value = Axios.post("http://localhost:3001/api/get-value",
    {user: userProp}).then((response) => {
        const recievedData = response.data;
        const dataValue = recievedData.map((val) => {
            return [val.value]
        })
            if (loading === true){
                setLoading(false);
            }
        return parseInt(dataValue);
    }).then((resp) => {
        setMoisture(resp) // if I turn this off still no go.
        return resp
    })
    return value
}, [userProp, loading])

const Data = React.useCallback(() => {
    try {
        return wait().then(getData)
    } catch (error) {
        setError(true);
        return error;
        }   
}, [wait, getData])

React.useEffect(() => {
    let isEffect = false
    if (props.location.state !== undefined) {
        Data().then((firstResponse) => {
            if (!isEffect){
                setMoisture(firstResponse)
            }
        })
    }
    return () => {
        isEffect = true;
    }
}, [props.location.state, Data, moisture]);  

标签: javascriptreactjsasynchronouspromiseuse-effect

解决方案


提供给 useEffect 的回调必须返回一个函数或未定义(如果提供了一个函数,这被认为是一个清理函数。清理函数用于分离事件侦听器,取消任何正在进行的请求,并防止如果组件被卸载,任何更新)

为了访问您的 http 请求产生的响应,您应该将其存储在一个状态中(您可以使用 useState 或 useReducer)

const [rest, setResp] = React.useState();

React.useEffect(() => {
 wait().then(_ => getData()).then(setResp);
}, [YOUR_DEPENDENCIES]);

// update jsx based on rest

根据您问题中的更新,您需要的是轮询

请查看下面的示例(请记住,这是说明可能解决方案的代码)

function usePolling(fetcher, interval) {
  const [payload, setPayload] = React.useState(null);
  
  React.useEffect(function () {
    // you must implement the error handling
    fetcher()
      .then(function (resp) {
        setPayload(resp)
      })
    
  }, [fetcher]);
  
  React.useEffect(function () {
    let timeoutId;
    
    function poll() {
      timeoutId = setTimeout(function () {
        // you must implement the error handling
        fetcher()
          .then(function (resp) {
            setPayload(resp)
            poll();
          })
      }, interval);
    }
    poll()
    
    return function () {
      clearTimeout(timeoutId);
    }
  }, [fetcher, interval]);
  
  return payload;
}


function App() {
  const payload = usePolling(function () {
    return Promise.resolve(Date.now())
  }, 3000);
  
 
  return (
    <div>polling payload: {payload}</div>
  )
}

ReactDOM.render(<App/>, document.getElementById('app'))
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
</head>
<body>
  <div id="app"></div>
</body>
</html>


推荐阅读