useEffect doesn't update state on route change

12,929

Solution 1

The effect you want is "When the location change then update my state", this is translated in useEffect code like this :

  useEffect(() => {
    detectHome();
    return () => {
      detectHome();
    };
  }, [location]);

Solution 2

If you are using react-router you can subscribe to location change event in your useEffect:

import {browserHistory} from 'react-router';

...
useEffect(() => {
  return browserHistory.listen(detectHome);
}, []);
...

This would subscribe your detectHome function for location change on mount and unsubscribe it on unmount.

Share:
12,929
Darren
Author by

Darren

Updated on August 10, 2022

Comments

  • Darren
    Darren almost 2 years

    I am looking for a solution to register the route change and apply new state using setState and useEffect. The current code below doesn't update functions of setState when the route is changed.

    For example, I register the pathname of / with location.pathname === '/' within createContext, if the pathname is / the setState of isHome is registered true, however if pathname is /page-1 setState is registered false.

    On browser reloads, onMount the state is correctly set, however on a route change using Link this does not. Also, please note that I am using Gatsby and in doing so, importing { Link } from 'gatsby'

    CreateContext.js

    export const GlobalProvider = ({ children, location }) => {
    
    
    const prevScrollY = useRef(0);
      const [state, setState] = useState({
        isHome: location.pathname === '/',
        // other states
      });
    
      const detectHome = () => {
        const homePath = location.pathname === '/';
        if (!homePath) {
          setState(prevState => ({
            ...prevState,
            isHome: false
          }));
        }
        if (homePath) {
          setState(prevState => ({
            ...prevState,
            isHome: true
          }));
        }
      };
    
      useEffect(() => {
        detectHome();
        return () => {
          detectHome();
        };
      }, [state.isHome]);
    
      return (
        <GlobalConsumer.Provider
          value={{
            dataContext: state,
          }}
        >
          {children}
        </GlobalConsumer.Provider>
      );
    };
    

    If I console.log(state.isHome) on pathname / I get true, any other pathnames I get false, however, if I change route, the current isHome state remains previous, until I scroll and useEffect applies.

    The point of registering the isHome state is to alter CSS per page.

    How can I update state with useEffect when changing route. Previously, I would have done this with componentDidUpdate and register prevProps.location.pathname against props.location.pathname, however, my understanding is that this is no longer necessary with the useEffect hook.