Here is a React component that can hold state and share context (within the component, in a “React Island.“)


Your logged in status: false

You need to click to log in.


Here is the code for this page:

//src/pages/auth-context.astro

---
import BaseLayout from '../../layouts/BaseLayout';
import AuthApp from '../../components/AuthApp.jsx';
import { Markdown } from 'astro/components';
---

<BaseLayout title="Auth State Context">
   <main>

      <Markdown>
         Here is a React component that can hold state (within the component, in a "React Island.")
      </Markdown>
      
      <hr />
      <AuthApp client:load />
      <hr />
      
      <Markdown>
         Here is the code for this page:
      </Markdown>

   </main>
</BaseLayout >

And this is the AuthApp.jsx component that’s being rendered.

//src/components/AuthApp.jsx
import React, { useState } from 'react';
import LogInButton from '../components/LoginButton.jsx';
import LogOutButton from '../components/LogoutButton.jsx';
import AuthContext from '../components/AuthContext.jsx';

const AuthApp = () => {
   const [auth, setAuth] = useState(false);
   
   const login = () => {
      setAuth(true);
   };
   
   const logout = () => {
      setAuth(false);
   };
   
   return (
      <>
         <p>Your logged in status: {auth} </p>
         <AuthContext.Provider value={{ auth: auth, login: login, logout: logout }}>
            <p>{auth ? 'Yay! You are logged in.' : 'You need to click to log in.'}</p>
            <LogInButton />
            <LogOutButton />
         </AuthContext.Provider>
      </>
   );
};
export default AuthApp;

With this context…

// src/components/AuthContext.jsx

import React, { createContext } from 'react';

const AuthContext = createContext({ 
   auth: null,
   login: () => {}, //For the sake of playing with context, I'm holding these functions in context, too. Normally, I wouldn't bother.
   logout: () => {},
});

export default AuthContext;

and some external button components that also accept their functions through context.

//Login Button at src/components/LoginButton.jsx
import React, { useContext } from 'react';
import AuthContext from '../components/AuthContext.jsx';

const LoginButton = () => {
   const auth = useContext(AuthContext);
   return (
      <> //NB: gratuitous fragment, really only necessary if returning more than one element
         <button onClick={auth.login}>Login</button>
      </>
   );
};

export default LoginButton;
//Logout Button at src/components/LogoutButton.jsx
import React, { useContext } from 'react';
import AuthContext from '../components/AuthContext.jsx';

const LogoutButton = () => {
   const auth = useContext(AuthContext);
   return (
      <>
         <button onClick={auth.logout}>Click To Logout</button>
      </>
   );
};
export default LogoutButton;