Search code examples
reactjsuse-effectuse-reducer

useEffect not triggering re-render when it's being used with useReducer


I can't trigger re-render even the state has changed. PageContainer calls loadPage and loadPage updates state without any inssue. But when the state has changed it dose not trigger re-rendering. It only shows inital state(pageName.loginPage). My expected result is pageName.profilePage since token is already stored on browser. I've also checked debugger state is clearly changed to pageName.profilePage

function PageContainer() {
    const { state, loadPage } = useContainer({
        reducer: loginStatusCheckReducer,
    });

    useEffect(() => {
        loadPage();
    }, [state]); // or [state.page]

    return (
        <>
           {state.page}
        </>
    );
}

And here is useContainer

function useContainer({ reducer }) {
    const [state, dispatch] = useReducer(reducer, { page: pageName.loginPage });
    const loadPage = () => {
        dispatch({ type: actionType.loadPage, dispatch });
    };

    return { state, loadPage };
}

This is the reducer function

function loginStatusCheckReducer(state, action) {
    if (action.type === actionType.loadPage) {
        const token = localStorage.getItem("token");
        if (token) {
            state.api = api(token);
            state.page = pageName.profilePage;
            return state;
        }
    }

    return state;
}


initial state: enter image description here

after loadPage enter image description here


Solution

  • Looking at the code, I will guess that is not triggering a re-render because your useEffect is passing an empty array, so it will not react to any state changes.

    Try adding the variable/state that will change once loaded on the useEffect

    function PageContainer() {
    const { state, loadPage } = useContainer({
        reducer: loginStatusCheckReducer,
    });
    
    useEffect(() => {
        loadPage();
    }, [state]); // here the effect will listen to state changes
    
    console.log('state.page', state.page);
    
    return (
        <>
           <h1>{state.page}</h1>
        </>
    );}