当前位置: 首页 > 知识库问答 >
问题:

React useReducer钩子状态在页面刷新后丢失

柯星辰
2023-03-14

当用户成功登录时,它将身份验证状态从null变为true,并且在登陆主页后,当我刷新页面时,它将初始化状态(authstate.js)设置为默认状态值,我希望即使在用户刷新页面后也能保持该状态。我使用的是hooks reducer

login.js

      import React, { useState, useContext, useEffect } from "react";
      import AlertContext from "../../context/alert/alertContext";
      import AuthContext from "../../context/auth/authContext";
      const Login = props => {
      const authContext = useContext(AuthContext);
      const { login, isAuthenticated,loading } = authContext;
      useEffect(() => {
      if (isAuthenticated) {
      props.history.push("/");
      }
      if (error === "Invalid Credentials") {
      setAlert(error, "danger");
      clearErrors();
      }
        // eslint-disable-next-line
      }, [error, isAuthenticated, props.history]);
      const [user, setUser] = useState({
      email: "",
      password: ""
      });
      const { email, password } = user;
      const onChange = e => setUser({ ...user, [e.target.name]: 
      e.target.value });
      const onSubmit = e => {
      e.preventDefault();
      if (email === "" || password === "") {
      setAlert("Please fill in all fields", "danger");
      removeLoading();
      } else {
      login({
      email,
      password
      });
      }
      };
      return (
      <div className="form-container">
      <form onSubmit={onSubmit}>
      <div className="form-group">
      <label htmlFor="email">Email Address</label>
      <input type="email" name="email" value={email} onChange={onChange}
       />
      </div>
      <div className="form-group">
      <label htmlFor="password">Password</label>
      <input
      type="password"
      name="password"
      value={password}
      onChange={onChange}

              />
            </div>
            <input
              type="submit"
              value="Login"
              className="btn btn-primary btn-block"
            />
          </form>
 </div>
      );
    };
    export default Login;

authstate.js

这是initialstate代码

 const AuthState = props => {

  const initialState = {
    //token: localStorage.getItem("token"),
    isAuthenticated: null,
    loading: false,
    user: null,
    error: null

  };


  const [state, dispatch] = useReducer(authReducer, initialState);
  // Load User
  const loadUser = async () => {
        if (localStorage.token) {
      console.log(localStorage.token)
      setAuthToken(localStorage.token);
    }

    try {

      const res = await axios.get("/api/auth");

      dispatch({ type: USER_LOADED, payload: res.data });
    } catch (err) {

      dispatch({ type: AUTH_ERROR });
    }
  };

// Login User
  const login = async formData => {
    const config = {
      headers: {
        "Content-Type": "application/json"
      }
    };

    try {
      const res = await axios.post("api/auth", formData, config);
//console.log(res.data)
      dispatch({
        type: LOGIN_SUCCESS,
        payload: res.data
      });

      loadUser();
    } catch (err) {
      dispatch({
        type: LOGIN_FAIL,
        payload: err.response.data.msg
      });
    }
  };
    return (
    <AuthContext.Provider
      value={{

        isAuthenticated: state.isAuthenticated,
        loading: state.loading,

        user: state.user,
        error: state.error,
        login,
        logout

      }}
    >
      {props.children}
    </AuthContext.Provider>
  );
};

导出默认的AuthState;

authreducer.js这是reducer钩子代码导入{

  REGISTER_FAIL,
  USER_LOADED,
  AUTH_ERROR,
  LOGIN_SUCCESS,
  LOGIN_FAIL,
  LOGOUT,
  CLEAR_ERRORS,
} from "../types";

export default (state, action) => {
  switch (action.type) {


    case USER_LOADED:

      return {
        ...state,
        isAuthenticated: true,
        loading: false,
        user: action.payload
      };
       case LOGIN_SUCCESS:

      localStorage.setItem("token", action.payload.token);
      return {
        ...state,
        ...action.payload,
        isAuthenticated: true,
        loading: false
      };

    case AUTH_ERROR:
    case LOGIN_FAIL:

      localStorage.removeItem("token");

      return {
        ...state,
        token: null,
        isAuthenticated: false,
        loading: false,
        user: null,
        error: action.payload
      };

        case REMOVE_LOADING:
          return {
            ...state,
            loading: false
          };
    default:

      return state;
  }
};

专用路由

import React, { useContext } from "react";
import { Route, Redirect } from "react-router-dom";
import AuthContext from "../../context/auth/authContext";

const PrivateRoute = ({ component: Component, ...rest }) => {
  const authContext = useContext(AuthContext);
  const { isAuthenticated } = authContext;

  return (

    <Route
      {...rest}
      render={props =>
        !isAuthenticated ? (
          <Redirect to="/login" />
        ) : (
          <Component {...props} />
        )
      }
    />
  );
};

export default PrivateRoute;

主页

import React, { useContext, useEffect } from "react";
import AuthContext from "../../context/auth/authContext";

const Home = () => {
  const authContext = useContext(AuthContext);

  useEffect(() => {
    //authContext.setLoading(true);
    authContext.loadUser();

    // eslint-disable-next-line
  }, []);
  return (
    <div className="grid-2">
      <div>
        <ContactForm />
      </div>
      <div>
        <ContactFilter />
        <Contacts />
      </div>
    </div>
  );
};

export default Home;  

共有1个答案

羊刚捷
2023-03-14

您可以将您的loggedin状态传递给reducer并更新您的初始状态。或者使用localstorage类似

   let initialState={
        loggedIn: localStorage.getItem('isLoggedin' ) || false;
    }
 类似资料:
  • 我的应用程序使用Firebase API进行用户身份验证,将登录状态保存为Vuex状态下的布尔值。 当用户登录时,我设置登录状态并相应地有条件地显示登录/注销按钮。 但是当页面刷新时,vue应用的状态丢失并重置为默认 这会导致一个问题,即使用户登录并刷新页面,登录状态也会被设置为false,并且显示登录按钮而不是注销按钮,即使用户保持登录状态... 我该怎么做才能防止这种行为 我应该使用cooki

  • 本文向大家介绍vuex页面刷新后数据丢失的方法,包括了vuex页面刷新后数据丢失的方法的使用技巧和注意事项,需要的朋友参考一下 1. 原因 (1)js代码是运行在内存中的,代码运行时的所有变量、函数都是保存在内存中。 (2)刷新页面,以前申请的内存被释放,重新加载脚本代码,变量要重新赋值。 (3)要想刷新后数据不丢失就必须把数据存储在外部,例如:Local Storage、Session Stor

  • 似乎$state.go('statename')就像浏览器中的后退按钮一样工作。缓存类型。 当状态发生变化时,我需要刷新页面,例如单击浏览器中的刷新按钮。 当状态改变时,我需要重新加载/刷新整个页面,基本上是重新初始化控制器。 已尝试使用$state。go('statename',{},{重新加载:true}),但没有效果。 我们将不胜感激

  • 我有一个对象的状态数组: 我有一个添加按钮,用于将对象添加到数组中,这是onclick事件的主体:

  • 我正在使用本教程学习AngularJS和ionic framework: http://www.htmlxprs.com/post/12/tutorial-on-using-parse-rest-api-and-ionic-framework-together 直到我在createTodo状态下创建一个新项,然后调用$state时,一切都很正常。go('todos')要返回到我的项目列表,以下是创

  • 我正在React中使用useState钩子,状态将不会在