Невозможно прочитать состояние, обновленное с помощью ловушки useReducer в поставщике контекста - PullRequest
1 голос
/ 02 апреля 2019

Я использую useReducer ловушку для управления своим состоянием, но мне кажется, что у меня проблема с чтением обновленного состояния в моем провайдере контекста.

Мой провайдер контекста отвечает за выборку некоторых удаленных данных и обновлениесостояние, основанное на ответах:

import React, { useEffect } from 'react';
import useAppState from './useAppState';


export const AppContext = React.createContext();

const AppContextProvider = props => {
  const [state, dispatch] = useAppState();

  const initialFunction = () => {
    fetch('/some_path')
      .then(res => {
        dispatch({ type: 'UPDATE_STATE', res });
      });
  };

  const otherFunction = () => {
    fetch('/other_path')
      .then(res => {
        // why is `state.stateUpdated` here still 'false'????
        dispatch({ type: 'DO_SOMETHING_ELSE', res });
      });
    }
  };

  const actions = { initialFunction, otherFunction };

  useEffect(() => {
    initialFunction();
    setInterval(otherFunction, 30000);
  }, []);

  return (
    <AppContext.Provider value={{ state, actions }}>
      {props.children}
    </AppContext.Provider>
  )
};

export default AppContextProvider;

и useAppState.js очень просто:

import { useReducer } from 'react';


const useAppState = () => {
  const reducer = (state, action) => {
    switch (action.type) {
      case 'UPDATE_STATE':
        return {
          ...state,
          stateUpdated: true,
        };
      case 'DO_SOMETHING_ELSE':
        return {
          ...state,
          // whatever else
        };
      default:
        throw new Error();
    }
  };


  const initialState = { stateUpdated: false };

  return useReducer(reducer, initialState);
};


export default useAppState;

Вопрос, как указано в комментарии выше, почему state.stateUpdated вotherFunction поставщика контекста все еще false и как я могу получить доступ к состоянию с последними изменениями в той же функции?

1 Ответ

1 голос
/ 02 апреля 2019

state никогда не изменится в этой функции

Причина, по которой state никогда не изменится в этой функции, заключается в том, что state обновляется только при повторном рендеринге.Поэтому, если вы хотите получить доступ к state, у вас есть два варианта:

  1. useRef, чтобы увидеть будущее значение state (вам придется изменить редуктор, чтобы это работало)
const updatedState = useRef(initialState);
const reducer = (state, action) => {
  let result;
  // Do your switch but don't return, just modify result

  updatedState.current = result;
  return result;
};

return [...useReducer(reducer, initialState), updatedState];
Вы можете сбросить setInterval после каждого изменения состояния, чтобы оно отображало наиболее актуальное состояние.Однако это означает, что ваш интервал может сильно прерваться.
const otherFunction = useCallback(() => {
  fetch('/other_path')
    .then(res => {
      // why is `state.stateUpdated` here still 'false'????
      dispatch({ type: 'DO_SOMETHING_ELSE', res });
    });
  }
}, [state.stateUpdated]);

useEffect(() => {
  const id = setInterval(otherFunction, 30000);
  return () => clearInterval(id);
}, [otherFunction]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...