简体   繁体   中英

Use of state from useReducer() outside of render function

I'm unable to access state current values outside of the render function. It always return the initial state value

I have a signalR connection and when I receive a message, I want to dispatch an action. The "problem" is: I'm using the same reducer for two state objects. Therefore, I want to check to which one I should dispatch the action.

Reducer:

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

Component:

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} />
  </>

The problem is in this line:

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

"processoSetor" is always empty. Even after the "ItemIniciado" action (code omitted) that sets the state before and renders everything fine.

If I comment this line, everything continues to render just fine.

So I was wondering if I have to use a single state and do these checks inside de reducer function, or am I doing something wrong that is preventing me from getting the actual value of the state outside the render function?

The problem arises due to closure, since your useEffect runs only on initial render, when it subscribes to hubConnection it refers to the updateProcesso function created on initial render which in the current lexical scope refers to the initial value of reducer state which is an empty object. When the component re-renders this function is recreated whereas the hubConnection callback still refers to the old function which uses to old values of reducer state.

To solve this issue you must pass processoSetor and processoUsuario in the dependency array to useEffect which is second parameter to useEffect

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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