I have to click back button twice to go back when using custom navigation in React.js

601 views Asked by At

I am trying to build a global navigation system for my React app where I store the states in local storage and URL. now when I need to go back, the first time when I click back it works. I restore the previous states. But from next back click I have to do it twice before I can go back to the previous state. the history is not updating on the first back click. The URL is also not changing on first click.

my code is as follows :

const useMyHook = (key) => {

  const [st1, setSt1] = useState(null);
  const [st2, setSt2] = useState(null);
  const [initialLoad, setInitialLoad] = useState(true); // to find if it is loaded

  useEffect(() => {

    const storedFilters = JSON.parse(localStorage.getItem(key));
    if (storedFilters && initialLoad) {
      setSt1(storedFilters.st1);
      setSt2(storedFilters.st2);
    }
    setInitialLoad(false); // once loaded set it to false
  }, [initialLoad, key]);

  useEffect(() => {
    const updateQueryParams = () => {
      const queryParams = new URLSearchParams();
      if (st1) queryParams.set('state1', st1);
      if (st2) queryParams.set('state2', st2);
      const queryString = queryParams.toString();
      const newUrl = `${window.location.pathname}?${queryString}`;

      window.history.pushState({ path: newUrl }, '', newUrl);
      localStorage.setItem(key, JSON.stringify({ st1, st2 }));
    };
    updateQueryParams();
  }, [st1, st2, key]);


  useEffect(() => {

    const handlePopState = () => {
      const queryParams = new URLSearchParams(window.location.search);
      setApps(queryParams.get('state1') ? parseInt(queryParams.get('state1')) : null);
      setLoc(queryParams.get('state2') ? parseInt(queryParams.get('state2')) : null);
    };


    window.addEventListener('popstate', handlePopState);

    return () => {
      window.removeEventListener('popstate', handlePopState);
    }
  }, []);


  return { st1, setSt1, st2, setSt2 };
};
1

There are 1 answers

0
I3B On

I believe this is happening because your app is running in strict mode:

StrictMode renders components twice (on dev but not production) in order to detect any problems with your code and warn you about them (which can be quite useful).

you can put an if to make sure that this combination of dependencies is new or you can fix your logic so you don't use useEffect other than when interacting with external systems. Read this from the official docs for more information: You Might Not Need an Effect

hope this might help!