Home > OS >  How to make header component know if user is logged in in React?
How to make header component know if user is logged in in React?

Time:03-12

I have a React project that has a HeaderComponent that exists for all routes in project like this:

function App() {
  return (
    <Fragment>
      <Router>
        <HeaderComponent />
        <Routes>
          <Route path="/login" element={<Login />}></Route>
          <Route path="/register" element={<Register />}></Route>
          <Route path="/" element={<LandingPage />}></Route>
        </Routes>
        <FooterComponent />
      </Router>
    </Fragment>
  );
}

And my problem is that the <HeaderComponent> is rendered when the website first loads but when the user logs in, the <HeaderComponent> is not aware of the changes because the component has already mounted.

So in my <HeaderComponent>, the componentDidMount function looks like this:

  componentDidMount() {
    AuthService.authorizeUser()
      .then((r) => {
        this.setState({ loggedIn: true });
      })
      .catch((error) => {
        this.setState({ loggedIn: false });
      });
  }

This only works if I refresh the page.

Basically, if a user successfully logs in (from the <Login> component), what is the proper way of making my HeaderComponent aware of this?

CodePudding user response:

You can use Context API to make AuthContext to share global state within your app:

// AuthContext.js
export const AuthContext = React.createContext({});

export const ThemeProvider = ({
  children,
}) => {
  // your context logic
  return (
    <AuthContext.Provider value={yourAuthValue}>
      {children}
    </AuthContext.Provider>
  );
}
export const useAuth = () => React.useContext(AuthContext);

// Layout.js
import { Outlet } from 'react-router-dom'

// Using `Outlet` to render the view within layout
export const Layout = () => {
  return (
    <>
      <HeaderComponent />
      <Outlet />
      <FooterComponent />
    </>
  )
}

// HeaderComponent.js
import { useAuth } from './AuthContext'

export const HeaderComponent = () => {
  // get state from auth context
  const { isLoggedIn } = useAuth()

  return // rest of your code
}

// App.js
function App() {
  return (
    <Fragment>
      <-- Wrap your app with AuthContext let other components within your app can access auth state !-->
      <AuthProvider>
        <BrowserRouter>
          <Routes>
            <Route path="/" element={Layout}>
              <Route index element={<LandingPage />} />
              <Route path="/login" element={<Login />} />
              <Route path="/register" element={<Register />} />
            </Route>
          </Routes>
        </BrowserRouter>
      </AuthProvider>
    </Fragment>
  );
}

CodePudding user response:

There are a couple of ways to do so. When you're facing a situation where you need to share the same state between multiple components, lifting the state up should be the first thing to try Check this codesandbox.
And some great blogposts to read, KCD - Prop Drilling, KCD - State Management with React

Such approach may cause "prop drilling" when you need the same state in deeply nested components and that's where the context API comes in handy. codesandbox

  • Related