Обновление состояния от ax ios вызов в useEffect hook - PullRequest
0 голосов
/ 07 февраля 2020

Я новичок, чтобы реагировать, и я только начал изучать хуки и контекст.

Я получаю некоторые данные из 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,
      };

На экране. js, я звоню getScreen и отправляю UUID, чтобы показать точный экран. Работает отлично. У меня возникает проблема, когда я пытаюсь получить API (каждые 3 секунды для тестирования) и обновить состояние nodeupdated на основе того, что он получает из API. Проблема в том, что 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 ... но в бесконечном количестве oop.

Дело в том, что это, казалось, прекрасно работало до того, как я преобразовал его в ловушки:

  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);
  }

Ответы [ 2 ]

0 голосов
/ 07 февраля 2020

Вы можете использовать что-то вроде этого. Просто замените console.log на ваш запрос API.

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

Либо замените foo, useEffect и добавьте requestId

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

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

  useEffect(() => {
    foo();
    setNodeupdated(screen.data)
  }, [requestId]);
0 голосов
/ 07 февраля 2020

Используйте пользовательский хук, например 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);

У Дана Абрамова есть отличная запись в блоге об этом

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

...