Error: Hydration failed because the initial UI does not match what was rendered on the server.
Tags: react, nextjs, javascript, webdev
Published: 2022-07-24 19:07:00

Take me to the [fix](#fix)

###Where I encountered the bug-

```javascript
export default function Nav() {
const user = getUser();

{user ? <AuthenticatedNav /> : <UnauthenticatedNav />} //this throws error
}
```

![error shown in the browser window:Error: Hydration failed because the initial UI does not match what was rendered on the server](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t97aocm0hq7yxjvsiez3.png)
This error notice provides no information that could lead us to problematic code, but the console does.
![same as above but more verbose](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k73e70d5vmpgknikg4v7.jpg)
#####but why?
![jakie chan confusion gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jttbs79kqieqamxaas1u.gif)

####What is causing this error?

>While rendering your application, there was a difference between the React tree that was pre-rendered (SSR/SSG) and the React tree that was rendered during the first render in the Browser. The first render is called Hydration which is a feature of React.
This can cause the React tree to be out of sync with the DOM and result in unexpected content/attributes being present. -[nextjs docs](https://nextjs.org/docs/messages/react-hydration-error#why-this-error-occurred)

_yes I kinda get it but still why_ 

####All I want to do is this-
If the user is logged in, render the `<AuthenticatedNav>` component; otherwise, render the `<UnauthenticatedNav>` component.

###let us understand what is "hydration" and why is it used-

Server-side rendering (SSR) is used by frameworks such as nextjs to increase performance (LCP & FCP) and user experience (SEO) it renders the app on the server first, duh! It returns a fully-formed HTML document to the user but apps are "dynamic" and not everything can be accomplished by HTML & CSS so We tell React to attach event handlers to the HTML to make the app interactive. 
This process of rendering our components and attaching event handlers is known as “**hydration**”. It is like watering the "dry" HTML with the "water" of interactivity(JS). After hydration, our application becomes interactive or "dynamic".
hydration and rehydration are often used interchangeably but during rehydration, the client-side JS includes the same React code used to generate it at compile time. 
It runs on the user's device and builds up a picture of what the world should look like. It then compares it to the HTML built into the document. This is a process known as **rehydration**

In a rehydration, React assumes that the DOM won't change. It's just trying to adapt the existing DOM
When a React app rehydrates, it assumes that the DOM structure will match. If it doesn't then you know what
![console error Error: Hydration failed because the initial UI does not match what was rendered on the server.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5531kxzj6xlvi5omqeuu.png)
so in our case, we cannot possibly know the `user` state on the server and `user` state will return undefined until it is mounted on the client 

####So how to fix this -
essentially we have two ways to Fix <a name="fix"></a> this

1. useEffect/useMounted hooks
2. wrapping in a component

####`useEffect` or `useMounted` custom hook
```javascript
export default function Nav() {
  const [hasMounted, setHasMounted] = React.useState(false);
  React.useEffect(() => {
    setHasMounted(true);
  }, []);
  if (!hasMounted) {
    return null;
  }
  const user = getUser();
{user ? <AuthenticatedNav /> : <UnauthenticatedNav />}
```
OR
####**`useHasMounted`** custom hook
```javascript
function useHasMounted() {
  const [hasMounted, setHasMounted] = React.useState(false);
  React.useEffect(() => {
    setHasMounted(true);
  }, []);
  return hasMounted;
}
```
#####Wrapping in a component
`<clientOnly>` component
```javascript
function ClientOnly({ children, ...delegated }) {
  const [hasMounted, setHasMounted] = React.useState(false);
  React.useEffect(() => {
    setHasMounted(true);
  }, []);
  if (!hasMounted) {
    return null;
  }
  return (
    <div {...delegated}>
      {children}
    </div>
  );
}
```
Then you can wrap it around whatever compenent you want to render client-side only-
```javascript
<ClientOnly>
  <Nav/>
</ClientOnly>
```

#####What I did -
`nav.js`
```javascript
import { UserState } from '../../context/userProvider'

export default function Nav() {
 UserState() ? <AuthenticatedNav /> : <UnauthenticatedNav />
}
```

`userProvider.js` //using a global user context provider
```javascript
export function UserState() {
 const { user } = useUser();
 const [isUserLoggedIn, setIsUserLoggedIn] = useState(false);
  useEffect(() => {
     setIsUserLoggedIn(!!user);
   }, [user]);
  return isUserLoggedIn;
}
```
🙏Thank you for reading I hope you found this informative; if you have any criticism, suggestions, or corrections, please leave them in the comments section.


![untill next time](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tw3bpv4u5i2c9679btn0.gif)