【问题标题】:Unable to get value of persisted state using redux-persist after the store is rehydrated商店重新水化后,无法使用 redux-persist 获取持久状态的值
【发布时间】:2017-10-04 03:35:47
【问题描述】:

假设我有一个 Home 组件,它只是执行 api 调用以从服务器获取所有作业:

import React, { Component } from 'react';
import { fetchHomeWorks } from '../actions';
import HomeWorkRow from '../component/HomeWorkRow';


class Home extends Component {

    componentDidMount() {
        this.props.fetchHomeWorks()
    }

    renderHomeWorks() {
        const { home_works, error, loading } = this.props;

        if(!error) {
            if(!loading){
                if(home_works.length >=1) {
                    return home_works.map(home_work => {
                        return <HomeworkRow key={uuid()} home_work={home_work} />
                    })
                }
                else
                    return <p className="pt-card col-xs-12 col-xs-offset-1 content"> No Task Yet :)</p> 
            }
            else 
                return <p>Loading...</p>
        }
    }

    render() {
        return (
            <Layout>
                { this.props.renderHomeworks() }
            </Layout>
        );
    }
}

const mapStateToProps = ({ home_work, persist }) => {
    return {
        home_works: home_work.home_works,
        persist: 
    };
};
export default connect(mapStateToProps, { fetchHomeWorks })(Home);

在页面刷新时,由于 componentDidMount() 生命周期,它当然会执行 api 调用。现在,我想更改它并使用 redux-persist 使用 persisted 数据,这样它就可以避免每次页面调用 api刷新了……

我正在使用redux-persist 库.. 这是我使用 redux persist() 的应用程序组件:

import React, { Component } from 'react';
import { Provider } from 'react-redux';
import {
  BrowserRouter as Router,
  Route,
} from 'react-router-dom';
import { compose, createStore, applyMiddleware } from 'redux';
import {persistStore, autoRehydrate} from 'redux-persist';
import thunk from 'redux-thunk';
import logger from 'redux-logger';

import rootReducer from './reducers/';


class App extends Component {
  render() {
    const store = createStore(rootReducer, {}, compose(applyMiddleware(thunk, logger), autoRehydrate()));
    persistStore(store);
    return (
      <Provider store={store}>
        <Router>
          <div>
            <Route exact path="/" component={LoginForm} />
           // ... some routes which doesnt matter
          </div>
        </Router>
      </Provider>
    );
  }
}

export default App;

由于 redux 记录器,我知道 resux persist 正在工作

现在,我如何获得持久状态的值?我尝试制作另一个减速器: persistReducer 从'../actions/types'导入{ PERSIST };

export default (state = [], action) => {
    switch(action.type) {
        case PERSIST:
            return { ...state, persistState: action.payload }
        default:
            return state;   
    }
};

并将其添加到rootReducer:

import { reducer as formReducer } from 'redux-form'

import { combineReducers } from 'redux';
import homeWorkReducer from './userReducer';
import persistReducer from './persistReducer';

export default combineReducers({
    home_works: homeWorkReducer,
    form: formReducer,
    persist: persistReducer
});

在我的Home 组件中,我使用

componentWillReceiveProps(nextProps) {

    if(nextProps.persist.persistState) {
        console.log(nextProps.persist.persistState.home_works.home_works)   
    }
}

并正确获取值:

那么如何正确做呢?

【问题讨论】:

  • 对不起,我正在尝试分析它。考虑到您当前的设置,这实际上是一个非常好的问题。您显然已经安装了 redux-persist,可能完全正确。我看到你的 mapStateToProps 里面有一个冒号。这绝对是您的代码中的错误,不确定当前是否在您的项目中。在我看来,您的商店应该以this.props.persist 的形式保存在组件中,这是一个包含通常在reducer 内state 上的属性的对象。感觉离工作很近。看起来只是使用持久存储的问题。
  • 其他人分析,你需要检查github.com/rt2zz/redux-persist
  • 您知道吗,看起来它应该在您的组件中以this.props.persist.persistState 的形式出现。你可以在你的渲染方法中 console.log 看看它是否显示数据吗?或 nextProps,大声笑,我已经筋疲力尽了。看起来它应该可以工作了。

标签: javascript reactjs redux persist


【解决方案1】:

旁注,但如果您反转 if 语句中的逻辑,您可以稍微清理一下代码:

这个:

renderHomeWorks() {
    const { home_works, error, loading } = this.props;

    if(!error) {
        if(!loading){
            if(home_works.length >=1) {
                return home_works.map(home_work => {
                    return <HomeworkRow key={uuid()} home_work={home_work} />
                })
            }
            else
                return <p className="pt-card col-xs-12 col-xs-offset-1 content"> No Task Yet :)</p> 
        }
        else 
            return <p>Loading...</p>
    }
}

可以变成:

renderHomeWorks() {
    const { home_works, error, loading } = this.props;

    if (error) return <p>Loading...</p>

    if (loading || !home_works) return <p className="pt-card col-xs-12 col-xs-offset-1 content"> No Task Yet :)</p> 

    return home_works.map(home_work => <HomeworkRow key={uuid()} home_work={home_work} />)
}
  1. 对于只有一个表达式的 if 语句,您可以省略 {}
  2. 0 是一个假值,所以 home_works.length === 0!home_works 都返回 true
  3. 如果函数只返回一个表达式(几乎在所有情况下),您可以使用带有粗箭头 =&gt; 语法的隐式返回

例如,home_works.map(() =&gt; something())home_works.map(() =&gt; { return something() }) 相同。如果 JSX 只返回一个 JSX 元素(例如 div 或一个组件),您也可以这样使用 JSX。

我刚刚向您展示的这段代码是有效的,因为 React 正在渲染 HomeWorks,它首先检查是否有错误——如果有,从渲​​染函数返回——然后,它检查它是否正在加载或 home_works是假的——如果是,从函数返回——最后,它继续渲染作业行列表。

【讨论】:

    猜你喜欢
    • 2022-11-11
    • 2018-08-14
    • 2019-04-14
    • 1970-01-01
    • 1970-01-01
    • 2017-01-19
    • 2022-12-31
    • 1970-01-01
    • 2017-10-08
    相关资源
    最近更新 更多