Использование состояния из useReducer () вне функции рендеринга - PullRequest
0 голосов
/ 29 марта 2019

Я не могу получить доступ к текущим значениям состояния вне функции рендеринга. Всегда возвращается начальное значение состояния

У меня есть соединение signalR, и когда я получаю сообщение, я хочу отправить действие. Проблема в том, что я использую один и тот же редуктор для двух объектов состояния. Поэтому я хочу проверить, к какому из них я должен направить действие.

Разбавление:

const processoReducer = (state, action) => {
  switch (action.type) {
    case "ProcessoIniciado":
      return {...action.payload};
    case "ItemIniciado":
      return { ...state, iniciados: state.iniciados + 1 };
    case "ItemConcluido":
    case "ItemErro":
      var arr = state.mbTiles.slice();
      arr.pop();
      return {
        ...state,
        executados: state.executados + 1,
        iniciados: state.iniciados - 1,
        mbTiles: [action.payload, ...arr]
      };
    default:
      return {...state};
  }
};

Компонент:

const mbtiles = props => {
  const [processoSetor, dispatchSetor] = useReducer(processoReducer, {});
  const [processoUsuario, dispatchUsuario] = useReducer(processoReducer, {});
...
useEffect(() => {
...
  hubConnection.on("ItemConcluido", mbtile => {
      updateProcesso(mbtile, "ItemConcluido");
    });
}, []);

const updateProcesso = (mbtileInfo, type) => {
    if (mbtileInfo.processo === processoSetor.id)
      dispatchSetor({ type, payload: mbtileInfo });
    else if (mbtileInfo.processo === processoUsuario.id)
      dispatchUsuario({ type, payload: mbtileInfo });
  };
...
return (
  <>
        <MbTilesContainer processo={processoUsuario} />
        <MbTilesContainer processo={processoSetor} />
  </>

Проблема в этой строке:

if (mbtileInfo.processo === processoSetor.id)

"processoSetor" всегда пуст. Даже после действия «ItemIniciado» (код не указан), которое устанавливает состояние до и отображает все нормально.

Если я прокомментирую эту строку, все будет отображаться нормально.

Так что мне было интересно, нужно ли мне использовать одно состояние и выполнять эти проверки внутри функции дередуктора, или я делаю что-то не так, что мешает мне получить фактическое значение состояния вне функции рендеринга?

1 Ответ

0 голосов
/ 29 марта 2019

Проблема возникает из-за закрытия, поскольку ваш useEffect выполняется только при начальном рендеринге, когда он подписывается на hubConnection, он ссылается на функцию updateProcesso, созданную при начальном рендере, которая в текущей лексической области действия ссылается на начальный значение состояния редуктора, которое является пустым объектом. Когда компонент повторно выполняет рендеринг, эта функция воссоздается, тогда как обратный вызов hubConnection по-прежнему ссылается на старую функцию, которая использует старые значения состояния редуктора.

Чтобы решить эту проблему, вы должны передать processoSetor и processoUsuario в массиве зависимостей в useEffect, который является вторым параметром useEffect

useEffect(() => {
...
  hubConnection.on("ItemConcluido", mbtile => {
      updateProcesso(mbtile, "ItemConcluido");
    });
}, [processoSetor, processoUsuario]);
...