reactjsreact-context

React is not updating the Context and the Provider


I have this handler and function to update my react context but it's not updating. It does not dispatch the action

This function switches accounts

 const loadAccountSwitch = useCallback(
 async (accountId, userId, userRoleName) => {
  if (!accountId || !userId || !userRoleName) return;
  try {
    setLoading(true);
    const results = await getToken(accountId, userId, userRoleName);
    const { user: apiUser,accessToken } = results.data;
    setLoading(false);
    if (!apiUser || typeof apiUser !== 'object' || !apiUser._id) { 
      console.error('Invalid apiUser:', apiUser);
      return;
    }
 
    console.log('after account switch', apiUser);
    console.log('isMountedRef',isMountedRef.current)
     if (isMountedRef.current) {
      handleClose();
      dispatch({ type: 'UPDATE_USER', 
        payload: { 
          user: apiUser 
        } 
      });
    }
   
      navigate(`${PATH_DASHBOARD.general.app}`);
      console.error('after navigating');
      handleClose();
   
  } catch (error) {
    setLoading(false);
    
  }
},
 [dispatch,  isMountedRef]

);

This function is the handler for the react context

 const handlers = {
 INITIALIZE: (state, action) => {
 const { isAuthenticated, user } = action.payload;
  return {
  ...state,
  isAuthenticated,
  isInitialized: true,
  user,
 };
},
 LOGIN: (state, action) => {
  const { user } = action.payload;
 console.log('State before LOGIN:', state);
console.log('Payload in LOGIN:', user);
return {
  ...state,
  isAuthenticated: true,
  user,
 };
},

 UPDATE_USER: (state, action) => {
  const { user } = action.payload;
  return {
  ...state,
   isAuthenticated: true,
  user,
  };
},
};

This is the Provider

function AuthProvider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState);
useEffect(() => {
const initialize = async () => {}
 initialize();
 }, []);

const login = async (email, password) => {
const url = `${HOST_API}/sign`;
const response = await axios.post(url, {
  email,
  password,
});
if (!response || response?.data === undefined || response?.data?.code === 1) {
  if (!response) {
    throw new Error('Could not make request');
  }
  throw new Error(response.data?.message);
}

const { accessToken, user } = response.data.data;
setSession(accessToken);
dispatch({
  type: 'LOGIN',
  payload: {
    user,
  },
  });
 };
const contextValue = useMemo(
() => ({
  ...state,
  method: 'jwt',
  login,
  
 }),
[state]
);
return (
  <AuthContext.Provider value={contextValue}>
  {children}
 </AuthContext.Provider>
  );
}

It runs the other codes in the account switch function but it particularly does not dispatch the action 'UPDATE_USER'


Solution

  • Here is a fixed version of your AuthProvider and the useReducer setup:

    function AuthProvider({ children }) {
      const [state, dispatch] = useReducer(reducer, initialState);
    
      // Example initialization function (add any logic if needed)
      useEffect(() => {
        const initialize = async () => {
          // Any necessary initialization logic (e.g., fetching user data)
        };
        initialize();
      }, []);
    
      const login = async (email, password) => {
        const url = `${HOST_API}/sign`;
        const response = await axios.post(url, {
          email,
          password,
        });
    
        if (!response || response?.data === undefined || response?.data?.code === 1) {
          if (!response) {
            throw new Error('Could not make request');
          }
          throw new Error(response.data?.message);
        }
    
        const { accessToken, user } = response.data.data;
        setSession(accessToken); // Ensure session is set properly
        dispatch({
          type: 'LOGIN',
          payload: {
            user,
          },
        });
      };
    
      const contextValue = useMemo(
        () => ({
          ...state,
          method: 'jwt',
          login,
          dispatch,  // Make sure dispatch is provided in contextValue
        }),
        [state]  // Dependency on state ensures context updates when state changes
      );
    
      return (
        <AuthContext.Provider value={contextValue}>
          {children}
        </AuthContext.Provider>
      );
    }
    
    export default AuthProvider;