【问题标题】:Redux, localStorage, and React: Getting an error when refreshing my pageRedux、localStorage 和 React:刷新页面时出错
【发布时间】:2020-04-27 17:44:54
【问题描述】:

我的目标是通过刷新让我的 React 状态保持不变。我使用浏览器的localStorageseen it done in a tutorial(如果您想查看,只需点击此处)。我想使用该解决方案,因为相对于淘汰 Redux Persist,它对我来说看起来很简单。

预期的结果是一个像以前一样刷新和重新加载的页面。相反,我得到一个错误。我怀疑错误的发生是因为 Redux 状态卸载(?),然后我的代码尝试将 const threadTitle 指向 this.props.posts[number] 中的状态,这当然不存在,因为刷新只是卸载了它。

我得到的错误如下:

TypeError: Cannot read property 'title' of undefined
fullThread.render
C:/Users/Roland/React_apps/reddit-knockoff/src/FullThread/FullThread.js:30
  27 | 
  28 |  // deliberate exclusion of 2nd parameter in .slice() to make it go til the end
  29 |  const number = this.props.location.pathname.slice(1);
> 30 |  const threadTitle = this.props.posts[number].title;
     | ^  31 |  let flair = null;
  32 |  const upVotes = this.props.posts[number].upvotes;
  33 |  const author = this.props.posts[number].author;

到目前为止,我已尝试观看教程视频并搜索 Google 的 StackOverflow 结果,以获取有关如何使用 localStorage 解决问题的提示。我已经启动并运行了一些代码,但这还不够。看看:

FullThread.js,错误信息指向的地方。

import React, { Component } from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";

class fullThread extends Component {
    constructor(props) {
        super(props);
        const stateFromStorage = localStorage.getItem("state");
        if (this.props.posts === null) {
            this.props.returnPostsToState(stateFromStorage);
        }
    }

    componentDidMount() {

        localStorage.setItem("state", this.props.posts);
    }

    render() {

        // deliberate exclusion of 2nd parameter in .slice() to make it go til the end
        const number = this.props.location.pathname.slice(1);
        const threadTitle = this.props.posts[number].title;
        const upVotes = this.props.posts[number].upvotes;
        const author = this.props.posts[number].author;
        const age = this.props.posts[number].age;
        const postText = this.props.posts[number].postText;


        return (
            <div>
                <div className="MainBody">
                    <h4>Thread titled: {threadTitle}</h4>
                    <p>Removed content. The constants threadTitle, upVotes, author, age and postText go here</p>

                </div>
            </div>
        );
    }
}

const mapDispatchToProps = dispatch => {
    return {
        returnPostsToState: stateFromStorage =>
            dispatch({ type: "RETURN", payload: stateFromStorage })
    };
};

const mapStateToProps = state => {
    return {
        posts: state.posts
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(fullThread);

posts.js,其中包含我的 Reducer

const initialPosts = {
    posts: [
        {
            id: 0,
            upvotes: 831,
            flair: null,
            title: "New? READ ME FIRST!",
            author: "michael0x2a",
            age: "2 years",
            comments: 15,
            postText:
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
        }
    ],
    loggedIn: false
};

const reducer = (state = initialPosts, action) => {
    if (action.type === "ADD_POST") {
        console.log("HEY: ", action.newPost);
        console.log(state.posts.concat(action.newPost.post.tempThread));
        return {
            ...state,
            // receives newPost data from app.js
            posts: state.posts.concat(action.newPost.post.tempThread)
        };
    }
    if (action.type === "RETURN") {
        console.log("RETURNED! ", action.payload);
        console.log("RETURNED: ", state.posts);
        return {
            ...state,
            posts: state.posts.concat(action.payload)
        };
    }

    return state;
};

export default reducer;

我会发布 app.js,但我认为它不相关。

我对我的代码的争论和错误是,我认为我的代码应该可以工作!首先,我在 componentDidMount() 方法中调用 localStorage.setItem("state", this.props.posts); 以使用我的帖子状态变量的内容设置我的 localStorage。然后当页面重新加载时,我的构造函数方法——首先触发,在组件生命周期中的任何其他代码之前!!! -- 调用this.props.returnPostsToState(stateFromStorage);,从而将全局 Redux 状态重置为“state From Storage”的内容,这是我的原始帖子内容!

我做错了什么?

我不知道如何实现它,但是,我认为有一些可行的解决方案,“if (stateHasReloaded) { const threadTitle = this.props.posts[number].title; }”我只是还不知道它到底是什么样子。

提前感谢您的帮助

【问题讨论】:

  • 这是由于没有将其转换为字符串。你可以通过 JSON.stringify 做到这一点。然后使用 JSON.parse 将其还原。它不适用于某些组件,但可以用于基本对象和数组。附带说明一下,对于这个用例,我建议您使用 react 的 Contexthooks 而不是 redux
  • 在 this.props.posts[number].title 之前,您是否在 this.props.posts 中获取数据???执行 console.log(this.props.posts) 并告诉我

标签: javascript reactjs redux local-storage


【解决方案1】:

我认为当您从本地存储中获取数据时,它将是字符串,因此您的组件将无法解析它。尝试从本地存储获取数据时解析数据。

 if (this.props.posts === null) {
      this.props.returnPostsToState(JSON.parse(stateFromStorage));
 }

当您存储到本地存储时,将您的数据字符串化为:

componentDidMount() {

    localStorage.setItem("state", JSON.stringify(this.props.posts));
}

为了更安全,您可以随时检查数据是否存在,因为您从 url 获取数字,因此任何人将其更改为帖子没有的数字:

const threadTitle = this.props.posts[number]?this.props.posts[number].title:'';

让我看看它是否有效。

【讨论】:

  • 我仍然收到TypeError: Cannot read property 'title' of undefined 错误。感谢您的尝试!
  • 两个小问题:1.您在控制台的reducer中获取数据并且打印数据正常吗? 2.const mapStateToProps = state =&gt; { console.log('checck what you are gettin here:',state); return { posts: state.posts }; };
  • 我已经更新了我的答案。请检查并告诉我。
  • 关于问题 #1:我的减速器状态确实可以打印到控制台。 console.log("300:", this.props.posts);产生“300:
  • `` 是什么意思?只是这样打印还是你的初始状态? console.log("RETURNED! ", action.payload); console.log("RETURNED: ", state.posts); 您在有效载荷中获取正确的数据?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-25
  • 2019-02-09
  • 2020-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-17
相关资源
最近更新 更多