刷新页面时 Redux Store 设置为 null

Posted

技术标签:

【中文标题】刷新页面时 Redux Store 设置为 null【英文标题】:Redux Store set to null when refresh the page 【发布时间】:2021-09-27 08:57:21 【问题描述】:

Index.js

Redux 商店

这是 Redux 存储文件,我在其中通过调度操作来设置经过身份验证的用户的详细信息。

import  createStore  from "redux";
function reducerFunction(state = authenticatedUser: null, action)                      
    console.log("It is working");
    if(action.type === "USER_LOGIN")
        console.log(action.payload);
        return authenticatedUser: action.payload
    
    return authenticatedUser: null

export const store = createStore(reducerFunction);

Login.js

这是我的登录页面。当用户成功登录时,我将发送一个操作来更新 redux 存储中的状态。在此,我正在调度一个操作以在 redux 商店中设置经过身份验证的用户详细信息。

import  useState  from "react";
import  Link, useHistory  from "react-router-dom";
import  useSelector, useDispatch  from "react-redux";
const Login = () => 
  const dispatch = useDispatch();
  const history = useHistory();
  const [email, setemail] = useState("");
  const [password, setpassword] = useState("");

  const emailChangeHandler = (e) => 
    setemail(e.target.value);
  ;

  const passwordChangeHandler = (e) => 
    setpassword(e.target.value);
  ;

  const submitHandler = async (e) => 
    e.preventDefault();
    const userData = 
      email,
      password,
    ;
    try 
      const response = await fetch("/login", 
        method: "POST",
        body: JSON.stringify(userData),
        headers: 
          "Content-Type": "application/json",
        ,
      );
      const data = await response.json();
      console.log(data);
      localStorage.setItem("jwt", data.token);
      localStorage.setItem("user",
        JSON.stringify(
          name: data.user.name,
          email: data.user.email,
          _id: data.user._id,
        )
      );
      dispatch( type: "USER_LOGIN", payload: data.user );        //Here I am dispatching an action to set the authenticated user details in redux store.
      history.push("/");
     catch (e) 
      console.log(e);
    
    setemail("");
    setpassword("");
  ;
  return (
    <div className="mycard">
      <div className="card auth-card input-field">
        <h2>Instagram</h2>
        <form onSubmit=submitHandler>
          <input type="text" placeholder="email" onChange=emailChangeHandler value=email />
          <input type="text" placeholder="password" onChange=passwordChangeHandler value=password />
          <button className="btn waves-effect waves-light" type="submit" name="action" > Submit </button>
        </form>
        <p>
          <Link to="/signup">Don't have an account?</Link>
        </p>
      </div>
    </div>
  );
;
export default Login;

Profile.js

这是经过身份验证的用户个人资料页面。在这里,我通过从 redux 存储中获取数据来显示 经过身份验证的用户的名称authenticatedUser.name

import  useEffect, useState  from "react";
import  useDispatch, useSelector  from "react-redux";
import classes from "./Profile.module.css";
const Profile = () => 
    const [images, setImages] = useState([]);
    const [image, setImage] = useState("");
    const [url, setUrl] = useState("");
    const dispatch = useDispatch();
    const authenticatedUser = useSelector(state => state.authenticatedUser);    //Here I am fetching authenticated user.


    useEffect(async() => 
        const response = await fetch("/myPost", 
            method: "GET",
            headers: 
                "Authorization": "Bearer " + localStorage.getItem("jwt"),
                "Content-Type": "application/json"
            
        )
        const data = await response.json();
        console.log(data);
        setImages(data);
    , [])

    return (
        <div>
            <div>
                <div>
                    <img className=classes.profile_image src="https://images.unsplash.com/photo-1534972195531-d756b9bfa9f2?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=750&q=80"/>
                </div>
                <div >
                    <h1>authenticatedUser.name</h1>
                    <div>
                        <h4>80 posts</h4>
                        <h4>80 followers</h4>
                        <h4>80 following</h4>
                    </div>
                </div>
            </div>

            <div className=classes.gallery>
                images.map(image => 
                    return <img src=image.image/>
                )
            </div>
        </div>
    );

export default Profile;

主要问题从这里开始。当我刷新页面时,它显示错误 Cannot read property 'name' of null。当我搜索此错误时,我知道当页面刷新时 redux 存储设置为默认值。然后我发现 redux-persist 会帮助我们将数据存储到本地存储。但是知道我不明白如何应用这个 redux-persist npm 包。请帮我。? 请告诉我所有这些假设是否正确?

【问题讨论】:

【参考方案1】:

Redux 数据将设置为 100% 正确的初始状态,您可以根据需要使用任何浏览器存储(localStorage/sessionStorage/cookies)..

我将分享存储完整 redux 存储并在浏览器刷新时检索的示例(理想情况下不推荐),您可以只保存浏览器刷新所需的数据。

这个方法会在更新商店时调用

store.subscribe(()=>
  // save a copy to localStorage
  localStorage.setItem('reduxState', JSON.stringify(store.getState()))
)

刷新页面时检查天气,我们在 localStorage 中有任何内容

const persistedState = localStorage.getItem('reduxState') 
                       ? JSON.parse(localStorage.getItem('reduxState'))
                       : 

如果我们有,我们可以在创建商店时传递它

const store = createStore(
      reducer, 
      persistedState,
     /* any middleware... */
)

重要提示:理想情况下不建议将完整的存储数据存储在 localStorage...

【讨论】:

以上是关于刷新页面时 Redux Store 设置为 null的主要内容,如果未能解决你的问题,请参考以下文章

如何在 react-redux 中调用页面刷新的函数?

即使我在 react/redux 中使用受保护的路由设置了身份验证,我仍然会被注销?当我刷新页面时

在反应中丢失页面刷新时的组件数据

React Redux 状态在页面刷新时丢失

手动实现redux

解决当点击页面刷新时,vue的store数据丢失问题