# Part 77: Streamlining User Authentication with Custom Hooks in React

<figure><img src="https://159896965-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3LclXKUpANLoSt8DPdYV%2Fuploads%2FJK8G3Yjm1qHwjGSqwUcV%2F1675674296261.jpeg?alt=media&#x26;token=989182c4-9098-4bba-8dd9-52aeb4b0f941" alt=""><figcaption><p>[Pages] React Query</p></figcaption></figure>

In our journey to build a seamless authentication system, we've already developed a `useSignIn` custom hook to handle user login. This hook efficiently manages the API request and updates the user data in the React Query cache. Our next task is to address the sign-out process, ensuring that the application state updates immediately when a user logs out. Let's explore how to implement this functionality using a custom hook called `useSignOut`.

### Enhancing Code with Constants

Before diving into the sign-out logic, let's make a small but impactful refactoring to improve code clarity and maintainability. Both `useSignIn` and `useUser` hooks use the same query key for the user data. By defining a common constant, `USER_QUERY_KEY`, we ensure consistency and make the code more readable.

```javascript
// File: hooks/user.js

import { useMutation, useQuery, useQueryClient } from 'react-query';
import { fetchJson } from '../lib/api';

const USER_QUERY_KEY = 'user';
```

### Addressing the Sign-Out Issue

Previously, signing out did not update the application state immediately, requiring a page reload to reflect the change. To resolve this, we'll implement a `useSignOut` hook that uses `useMutation` to handle the logout request and updates the user data in the cache.

#### Implementing `useSignOut`

Let's create the `useSignOut` hook to encapsulate the sign-out logic.

```javascript
// File: hooks/user.js

export function useSignOut() {
  const queryClient = useQueryClient();
  const mutation = useMutation(() => fetchJson('/api/logout'));
  return async () => {
    await mutation.mutateAsync();
    queryClient.setQueryData(USER_QUERY_KEY, undefined);
  };
}
```

#### Key Features of `useSignOut`

1. **Mutation Setup**: Utilizes `useMutation` to prepare the logout API request.
2. **Cache Update**: Sets the user data in the React Query cache to `undefined` after logout, ensuring the UI updates immediately.

### Refactoring the NavBar Component

With `useSignOut` ready, we can simplify the NavBar component by replacing the old sign-out logic with our new hook.

```javascript
// File: components/NavBar.js

import Link from 'next/link';
import { useSignOut, useUser } from '../hooks/user';

function NavBar() {
  const user = useUser();
  const signOut = useSignOut();

  console.log('[NavBar] user:', user);
  return (
    <nav>
      <ul>
        {user ? (
          <>
            <li>Welcome, {user.name}</li>
            <li>
              <button onClick={signOut}>Sign Out</button>
            </li>
          </>
        ) : (
          <li>
            <Link href="/sign-in">Sign In</Link>
          </li>
        )}
      </ul>
    </nav>
  );
}

export default NavBar;
```

#### Simplifications in NavBar

* **Direct Sign-Out Handling**: The `signOut` function from `useSignOut` is directly used as an `onClick` handler, eliminating the need for a separate handler function.
* **Immediate UI Update**: The NavBar now updates immediately upon sign-out, thanks to the cache update in `useSignOut`.

### Testing the Implementation

To ensure everything works as expected, follow these steps:

1. **Sign In**: Log in using valid credentials and verify that the NavBar updates to reflect the signed-in state.
2. **Sign Out**: Click the "Sign Out" button and confirm that the NavBar updates immediately to show the signed-out state.
3. **Network Requests**: Use browser developer tools to verify that the appropriate network requests are made and that no unnecessary requests occur after signing out.

### Conclusion

By creating a `useSignOut` custom hook, we've effectively addressed the sign-out issue, ensuring that the application state updates promptly when a user logs out. This approach not only improves the user experience but also keeps our codebase organized and maintainable. As you continue building applications, consider leveraging custom hooks to encapsulate common logic, making your React components simpler and more focused.
