繁体   English   中英

从 useEffect 钩子中的 axios 调用更新状态

[英]Update state from axios call in useEffect hook

我是反应的新手,我刚刚开始学习钩子和上下文。

我使用以下代码从 API 获取一些数据:

const getScreen = async uuid => {

    const res = await axios.get(
      `${url}/api/screen/${uuid}`
    );

    dispatch({
      type: GET_SCREEN,
      payload: res.data
    });
  };

继续使用减速器。

case GET_SCREEN:
      return {
        ...state,
        screen: action.payload,
      };

在 Screen.js 中,我正在调用getScreen并发送UUID以显示确切的屏幕。 效果很好。 我遇到的问题是当我尝试获取 API(每 3 秒进行测试)并根据它从 API 检索的内容更新nodeupdated的状态时。 问题是, screen.data总是未定义的(因为它是异步的?)

import React, {
  useState,
  useEffect,
  useContext,
} from 'react';
import SignageContext from '../../context/signage/signageContext';

const Screen = ({ match }) => {
  const signageContext = useContext(SignageContext);

  const { getScreen, screen } = signageContext;

  const [nodeupdated, setNodeupdated] = useState('null');

  const foo = async () => {
    getScreen(match.params.id);

    setTimeout(foo, 3000);
  };

  useEffect(() => {
    foo();
    setNodeupdated(screen.data)
  }, []);

如果我删除 [] 实际上确实从 api 获取数据......但是在一个无限循环中。

问题是在我将它转换为钩子之前,这似乎工作得很好:

  componentDidMount() {
    // Get screen from UUID in url
    this.props.getScreen(this.props.match.params.id);

    // Get screen every 30.5 seconds
    setInterval(() => {
      this.props.getScreen(this.props.match.params.id);

      this.setState({
        nodeUpdated: this.props.screen.data.changed
      });
    }, 3000);
  }

使用像useInterval这样的自定义钩子

function useInterval(callback, delay) {
  const savedCallback = useRef();

  useEffect(() => {
    savedCallback.current = callback;
  });

  useEffect(() => {
    function tick() {
      savedCallback.current();
    }

    let id = setInterval(tick, delay);
    return () => clearInterval(id);
  }, [delay]);
}

然后在你的组件中

 useInterval(() => {
    setCount(count + 1);
  }, delay);

丹·阿布拉莫夫 (Dan Abramov) 有一篇关于此的精彩博文

https://overreacted.io/making-setinterval-declarative-with-react-hooks/

你可以使用这样的东西。 只需将 console.log 替换为您的 API 请求。

  useEffect(() => {
    const interval = setInterval(() => {
      console.log("Making request");
    }, 3000);
    return () => clearInterval(interval);
  }, []);

或者,替换foouseEffect并添加 requestId

 const [requestId, setRequestId] = useState(0);

 const foo = async () => {
    getScreen(match.params.id);
    setTimeout(setRequestId(requestId+1), 3000);
  };

  useEffect(() => {
    foo();
    setNodeupdated(screen.data)
  }, [requestId]);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM