首页 > 解决方案 > 上下文很慢或被调用两次

问题描述

我用于身份验证的上下文存在问题。如果我在登录时 console.log,首先我得到错误,然后一秒钟后它再次使用令牌等记录。所以,我的代码有问题。

这是我的身份验证钩子:

import { useState, useCallback, useEffect } from "react";

export const useAuth = () => {
  const [token, setToken] = useState(false);
  const [userId, setUserId] = useState(false);

  const login = useCallback((uid, token) => {
    setToken(token);
    setUserId(uid);
    localStorage.setItem(
      "userData",
      JSON.stringify({
        userId: uid,
        token: token,
      })
    );
  }, []);

  const logout = useCallback(() => {
    setToken(null);
    setUserId(null);
    localStorage.removeItem("userData");
  }, []);

  useEffect(() => {
    const storedData = JSON.parse(localStorage.getItem("userData"));
    if (storedData && storedData.token) {
      login(storedData.userId, storedData.token);
    }
  }, [login]);

  return { token, login, logout, userId };
};

身份验证上下文:

import { createContext } from "react";

export const AuthContext = createContext({
  isLoggedIn: false,
  userId: null,
  token: null,
  login: () => {},
  logout: () => {},
});

我遇到问题的组件示例(基本上在我使用此身份验证上下文的所有组件中)

import React, { useContext, useState } from "react";
import AdminCard from "../components/adminCards/AdminCard";
import { AuthContext } from "../../shared/context/auth-context";

const Dashboard = () => {
  const auth = useContext(AuthContext);
  console.log(auth);
  return (
    <div className="admin-wrapper">
      <div className="main-panel">
        <div className="row">
          <div className="wrapper">
            <div className="col-3">
              <AdminCard title="Contact Enquiries" />
              <AdminCard title="Card 2" />
              <AdminCard title="Card 3" />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default Dashboard;

在控制台中,我首先看到“false”,然后一秒钟后看到“auth”的内容。

App.js 示例

const App = () => {
   const { token, login, logout, userId } = useAuth();
  return (
    <>
      <AuthContext.Provider
        value={{
          isLoggedIn: !!token,
          token: token,
          userId: userId,
          login: login,
          logout: logout,
        }}
      >
 <Router>
<Switch>
   <Route path="/" exact>
    <Dashboard />
   </Route>
</Switch>
</Router>
</AuthContext.Provider>
</>
};

export default App;

问题的一个示例是,如果我通过单击链接登录并导航到仪表板,我没有问题。如果我在仪表板上并刷新浏览器,则会收到 403 错误并且请求失败,因为在发送请求时令牌尚不可用。

  useEffect(() => {
    const getItems = async () => {
      const config = {
        method: "get",
        url: "http://localhost:8000/api/admin/somedata",
        headers: { Authorization: "Bearer " + auth.token },
      };
      const responseData = await Axios(config);
      setItems(responseData.data);
      console.log(responseData.data);
    };
    getItems();
  }, []);

澄清一下,如果我刷新浏览器,我只会遇到这个问题。

标签: reactjsreact-hooksreact-context

解决方案


这就是 React 本身。你可以做的是你可以使用如下的 useEffect 钩子,

useEffect(() => {
  auth && doSomethingWithAuth(auth);
}, [auth])

但是,理想的解决方案是在读取您的身份验证令牌时显示一些加载组件。您基本上可以将您的提供者提取为另一个组件。然后您可以尝试在您的提供程序组件中读取您的 auth 变量。在开始读取操作时,将状态设置为 authLoading 并在 auth 变为真时将其设置为 false(再次使用 useEffect 挂钩)。最后,如果 authLoading === true,则显示一些加载组件/文本,否则显示提供者的孩子。

希望这可以帮助!


推荐阅读