skip to Main Content

I would like to show/hide links depending on what the user is authorized to do. Here is my first try:

const Navbar = () => {
  const { canDo, ...} = useUser(); //A Zustand store
  return (
    <>
      <div>
        <ul>
          {canDo && (
            <li>
              <Link href="/somelink">Something</Link>
            </li>
          )} ...//more options

I get this error on screen load or refresh
Error: Hydration failed because the initial UI does not match what was rendered on the server.
Warning: Expected server HTML to contain a matching "li" in "ul".

Second try – useEffect

const Navbar = () => {
const Navbar = () => {
  const { canDo, ...} = useUser(); //A Zustand store
  var doit = false;
  useEffect(() => {
    doit = canDo;

  }, [canDo, ...]);

       <ul>
          {doit && (
            <li>
              <Link href="/somelink">Something</Link>
             </li>

This did not work – the navbar never refreshed.

The last thing I tried was to return different menus based on conditions.
That didn’t work either – I got the hydration error on refresh

The issue is the Zustand store – on a browser refresh, the store (canDo) is cleared, then reloaded. So what React rendered on the server is different than what is rendered on the client.
Any suggestions?

I did solve my problem in a very un-React type of way – in the useEffect I set/clear the display style attributes of the "li" elements. Yeah, I know – DOM manipulation in React bad.

2

Answers


  1. Chosen as BEST ANSWER

    This worked https://codesandbox.io/s/nextjs-zustand-example-forked-bnpfz?file=/pages/index.tsx

    const useHasHydrated = () => {
      const [hasHydrated, setHasHydrated] = useState<boolean>(false);
    
      useEffect(() => {
        setHasHydrated(true);
      }, []);
    
      return hasHydrated;
    };
    ...
    const Navbar = () => {
      const hasHydrated = useHasHydrated();
    ...
     {hasHydrated && canDo && (
                <li>
                  <Link href="/caando">Can Do</Link>
                </li>
              )}
    

  2. Page renders, the useEffect is firing, if a value inside [] of useEffect was changed, the page will be reloaded again.
    Hydration error can be because your ul doesn’t contain li tags (when doit and canDo are undefined).

    You can use the code from here: https://react.dev/reference/react/useEffect#fetching-data-with-effects

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search