Home > OS >  How to use AuthContext inside of a class component?
How to use AuthContext inside of a class component?

Time:03-12

I have an auth-context.js file that looks like this following:

import React, { createContext, useState } from "react";

const AuthContext = createContext({});

const AuthProvider = (props) => {
  const [loggedIn, setLoggedIn] = useState(false);

  const login = () => {
    setLoggedIn(true);
  };

  const logout = () => {
    setLoggedIn(false);
  };

  const authContextValue = {
    login,
    loggedIn,
    logout,
  };
  return <AuthContext.Provider value={authContextValue} {...props} />;
};

const useAuth = () => React.useContext(AuthContext);

export { AuthProvider, useAuth };

I am trying to use this to set up authorization, but I am unable to get it to work because this is a function and I need to use it in a class component.

This is how I tried using it in the class component:

import { useAuth } from "../auth-context";

// the below is used when a user clicks login
const { login } = useAuth();
login();

This is the error I get:

Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app

So how can I use AuthContext? Does it need to be converted to a class component or something else?

This is my index.js file:

ReactDOM.render(
  <React.StrictMode>
    <AuthProvider>
      <App />
    </AuthProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

And my App.jsfile:

function App() {
  const { loggedIn } = useAuth();
  console.log("Is Logged in: "   loggedIn);

  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>
  );
}

export default App;

CodePudding user response:

Option 1 - create a new component that wraps the Login component, and use Context.Consumer, and pass the context values via the props:

const WrappedLogin = () => (    
  <AuthContext.Consumer>
    {authProps => <Login {...authProps} />}
  </AuthContext.Consumer>
)

In the auth-context.js file export AuthContext as well, so you can import it:

export { AuthProvider, useAuth, AuthContext };

Option 2 - create a new component that wraps the Login component, and use useAuth to get props, and pass them to the Login component:

const WrappedLogin = () => {
  const authProps = useAuth();

  return <Login {...authProps} />
}

With options 1 & 2, you'll get the AuthContext values via the props:

class Login extends React.Component {
  render() {
    const { isLoggedIn } = this.props;
  }
}

Option 3 - If this is the only context that the component is going to consume, you can use contextType. In this case you can consume your AuthContext values via this.context:

class Login extends React.Component {
  render() {
    const { isLoggedIn } = this.context;
  }
}
Login.contextType = AuthContext;

In the auth-context.js file export AuthContext as well, so you can import it:

export { AuthProvider, useAuth, AuthContext };
  • Related