I'm having trouble storing data persistently.
My case is when user logs in, I store JWT in web storage. However, I need to store user's information, such as user nickname or id.
I am trying to render user nickname in <header />.
I tried three different methods.
first one is using recoil, global state library. It didn't go well because whenever I refresh the page, every atoms were back to their initial value.
second one is using recoil-persist. I used recoil-persist or redux-persist in React. However, since recoil-persist works based on localStorage, I had a problem in hydration on Next.js. (localStorage doesn't exist in SSR, therefore hydration error occurs.)
last one I'm currently using is recoil and localStorage. Here's the code.
import { useRecoilValue } from 'recoil';
import { userNicknameAtom } from 'atoms/atom';
import { useEffect, useState } from 'react';
import styles from './header.module.scss';
function Header() {
  const [nick, setNick] = useState('');
  const user = useRecoilValue(userNicknameAtom);
  useEffect(() => {
    if (user) {
      localStorage.setItem('nickname', user);
    }
  });
  useEffect(() => {
    const id = localStorage.getItem('nickname');
    if (id) {
      setNick(id);
    } else {
      setNick('');
    }
  });
  return (
    <header className={styles.header}>
      {nick}
    </header>
  );
}
export default Header;
I am giving no dependency to useEffect to make sure codes inside useEffect runs every render. This works quite well.
However, I'm wondering whether this is the best approach to handle user info in Next.js If I can simply modify my code, I would like to know.
Making a localStorage in Next.js persist is very frustrating, but it is possible, this is a link that I think would help one who wants to store some user preferences and settings, without setting or adding a modal and db to store the user's input. How to persist data in Next.js with localStorage and no libraries.
Here is a demo
In a real app situation you would have a backend which would return your user data (automatically based on a token which is normally saved as a cookie). So each time your app is initialised you would make a request to get your user data and store it in your state management (redux, recoil, etc).
But in your case you want to make sure that you update your localStorage each time your user changes (I don't think there is any other case you want to update the localStorage). So your first useEffect should have user value in the dependency array like this:
  useEffect(() => {
    if (user) {
      localStorage.setItem('nickname', user);
    }
  }, [user]);
If the user value hasn't changed it doesn't make sense to update it with the same value.
Also I think you don't need second useEffect if you add the state setting to your first one (so in the end use just one useEffect which looks like this:
  useEffect(() => {
    if (user) {
      localStorage.setItem('nickname', user);
      setNick(user);
    }
  }, [user]);
  
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With