Alfrex92
Alfrex92

Reputation: 6788

Only show Popup one time with React (local storage)

I would like to show the popup only one time with React Hooks.

  1. Access for the first time to example.com/campaign/1234
  2. Show popup
  3. Close or refresh the page.
  4. Access again to example.com/campaign/1234 and don't show popup
  5. Access for the first time to example.com/campaign/0000 (is a different URL)
  6. Show popup
  7. Close or refresh the page
  8. Access again to example.com/campaign/0000 or example.com/campaign/1234 and the popup is not being displayed

Any idea of how to do it? I know that I need to use local storage but how can I trigger the event when the user closes or refreshes the page?

Here is a sandbox.

I also read this thread but it doesn't mention how to do it with Hooks

Upvotes: 1

Views: 2835

Answers (1)

Lionel Rowe
Lionel Rowe

Reputation: 5926

If you never use the setStickyState callback from the custom hook, the state will just remain at its initial value.

It seems like setStickyState also has a bug in it, where it won't update if the key has changed. Here's an enhanced version that I've called useLocalStorage, which should work more reliably:

export function useLocalStorage(key, initialDefault) {
  const [val, setVal] = useState(() => {
    const localStorageVal = localStorage.getItem(key);

    return localStorageVal !== null
      ? JSON.parse(localStorageVal)
      : initialDefault;
  });

  useEffect(() => {
    if (localStorage.getItem(key) === null) {
      setVal(initialDefault);
    }
  }, [key, initialDefault]);

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(val));
  }, [val, key]);

  return [val, setVal];
}

You can then use it like this:

const [visited, setVisited] = useLocalStorage(pageId, false);

const navigateAway = useCallback(() => {
  setVisited(true)
}, [setVisited])

useEffect(() => {
  // if user navigates away to a completely different site
  // or refreshes the page etc
  window.addEventListener("beforeunload", navigateAway);

  // if user navigates to another page on the same site
  return () => {
    navigateAway();
    window.removeEventListener("beforeunload", navigateAway);
  };
}, [pageId, navigateAway]);

// ...

<dialog open={!visited}>
  <p>Welcome to page {pageId}!</p>
  <button onClick={() => setVisited(true)}>
    Don't show again on this page
  </button>
</dialog>

Here's a demo (with TypeScript):

useLocalStorage demo

Upvotes: 2

Related Questions