如何在 class 组件中使用 AuthContext?

How to use AuthContext inside of a class component?

我有一个 auth-context.js 文件,如下所示:

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

我正在尝试使用它来设置授权,但我无法让它工作,因为这是一个函数,我需要在 class 组件中使用它。

这是我在 class 组件中尝试使用它的方式:

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

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

这是我得到的错误:

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

那么我该如何使用AuthContext呢?是否需要将其转换为 class 组件或其他组件?

这是我的 index.js 文件:

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

还有我的App.js文件:

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;

选项 1 - 创建一个包装 Login 组件的新组件,并使用 Context.Consumer,并通过 props 传递上下文值:

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

auth-context.js 文件中也导出 AuthContext,所以你可以导入它:

export { AuthProvider, useAuth, AuthContext };

选项 2 - 创建一个新的组件来包装 Login 组件,并使用 useAuth 获取道具,并将它们传递给 Login 组件:

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

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

使用选项 1 和 2,您将通过道具获得 AuthContext 值:

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

选项 3 - 如果这是组件将要使用的唯一上下文,您可以使用 contextType。在这种情况下,您可以通过 this.context:

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

auth-context.js 文件中也导出 AuthContext,所以你可以导入它:

export { AuthProvider, useAuth, AuthContext };