How useContext Can Easily Create Site-Wide Conditionally Rendered Context.
Published: 2023-09-24 20:57:31

Authenticating user logins can be complex especially when needing to alter content your site using conditional rendering. If only there was a way to use a setState site-wide in order to change a logged in user's content. Fortunately such a thing does exist in react called useContext that can create a component that you can wrap your entire App.js file to give access to a setState in every component. If this doesn't make much sense just understand that once set up properly you won't to need pass props down each child element known as prop drilling to use it in a component. 

For now look at how we can setup a useAuthContext component using useContext.

```
// AuthContext.js
import React, { createContext, useContext, useState } from 'react';

const AuthContext = createContext();

export const useAuth = () => useContext(AuthContext);

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);

  const login = (userData) => {
    // Implement your authentication logic here, e.g., calling an API
    setUser(userData);
  };

  const logout = () => {
    // Implement your logout logic here
    setUser(null);
  };

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};
```

This part is a little confusing because we are defining a component within a component but what is happening is we are setting up a useContext that is wrapped in the useAuth custom hook so that we have access to all of the elements in our AuthContext.js file. We then define AuthProvider which manages the state for authentication of logging in and out for the children of this component. In the return statement we see AuthContext.Provider component with the props for user, login and logout that will passed to its children.

Basically this code will make the user, login and logout props available to any components that are children of AuthContext component. We will now put everything in our app inside the AuthContext component. See the code below:

```
// App.js
import React from 'react';
import { AuthProvider } from './AuthContext';
import Home from './Home'; // Import your Home component or any other component you want to conditionally render

function App() {
  return (
    <AuthProvider>
      <div className="App">
        {/* Other components */}
        <Home />
      </div>
    </AuthProvider>
  );
}

export default App;
```
Notice that AuthProvider wraps our Home component and any other ones we type here. Now we can use the props from our AuthContext file to conditionally render content for a user as well as give keep the user logged in when navigating the site. See code for Home.js:

```
// Home.js or any component you want to conditionally render
import React from 'react';
import { useAuth } from './AuthContext';

function Home() {
  const { user, login, logout } = useAuth();

  return (
    <div>
      <h1>Welcome to Our Website</h1>
      {user ? (
        <div>
          <h2>Welcome, {user.name}!</h2>
          <button onClick={logout}>Logout</button>
        </div>
      ) : (
        <div>
          <h2>You are not logged in.</h2>
          <button onClick={() => login({ name: 'John' })}>Login</button>
        </div>
      )}
    </div>
  );
}

export default Home;
```

Here we can see that the user variable is able to conditionally render context via our imported and destructed lines here:

```
import React from 'react';
import { useAuth } from './AuthContext';

function Home() {
  const { user, login, logout } = useAuth();
```
 

And that's it, this is all we need to use conditionally render webpages for a logged in user on a few pages on our website or even every page. The setup is a little complex but once set up we can change the look and functionality just by implementing useContext and wrapping our children components in our useContext component.