提问者:小点点

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


当用户成功登录时,它将身份验证状态从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个答案

匿名用户

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

   let initialState={
        loggedIn: localStorage.getItem('isLoggedin' ) || false;
    }