【问题标题】:React Redux Refresh issueReact Redux 刷新问题
【发布时间】:2017-02-21 17:43:42
【问题描述】:

我正在使用 react-redux,但我遇到了刷新页面时我的 redux 状态丢失的问题。

在我继续之前,这是我可能搞砸的场景。

问题一:我可以连接到多个布局吗?

我有一个仪表板和一个“应用”布局。两者都有不同的布局。我以相同的方式连接两者:

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actionCreators from '../actions/actionCreators';

function mapStateToProps(state) {
  return {
    profile: state.profile,
    child: state.child,
  }
}

function mapDispachToProps(dispatch) {
  return bindActionCreators(actionCreators, dispatch);
}

const LayoutApp = connect(mapStateToProps, mapDispachToProps)      (DashboardLayout);

export default LayoutApp;

仪表板连接得很好。我可以在需要时点击减速器并更新商店,但是仪表板链接到应用程序以进行数据操作的某些部分供您使用。当它链接时,我按预期获取道具中的数据,但是一旦应用布局中的任何页面刷新,我就会丢失 maptoprops 发送的道具。

我尝试将其合并到一个主布局中,但这似乎具有相同的效果。当我第一次收到数据时,我也尝试立即保存状态,但刷新时它似乎也丢失了,这让我认为它正在重置它。

总结: - DashboardLayout(连接到redux) - AppLayout(连接到redux)但是在页面刷新后它会丢失Applayout的道具并且需要的数据消失了。

【问题讨论】:

  • 该状态仅在您的初始页面加载的生命周期内存在。您可以使用 redux-persist 保持状态并对其进行再水化。
  • 请注意,@MarioTacke 提到的 redux-persist 只是您拥有的几十个选项之一。你可以将你的状态树持久化到服务器、本地存储、cookie,无论你想要什么(并且适合媒体)。重点仍然存在 - 默认情况下,状态树无法自行重新加载页面,它需要保存在某个地方。
  • 为什么不在这两个布局之上的层次结构中创建一个状态呢?
  • 为什么不在这两个布局之上的层次结构中创建一个状态呢?

标签: reactjs redux react-redux


【解决方案1】:

了解 redux-persist

https://github.com/rt2zz/redux-persist

您可以使用安装它

npm i --save redux-persist

persistStore 是允许您持久存储的功能。

import {persistStore} from 'redux-persist'

而 autoRehydra 是在状态需要重新水化时执行的操作

import {autoRehydrate} from 'redux-persist'

以下是可能有用的结构。

import {compose, applyMiddleware, createStore} from 'redux'
import {persistStore, autoRehydrate} from 'redux-persist'

// add `autoRehydrate` as an enhancer to your store (note:  `autoRehydrate` is not a middleware)
const store = createStore(
     reducer,
     undefined,
     compose(
        applyMiddleware(...),
        autoRehydrate()
     )
)

// begin periodically persisting the store
persistStore(store)

然后是你的减速器

 import {REHYDRATE} from 'redux-persist/constants'
 //...
 case REHYDRATE:
   var incoming = action.payload.myReducer
   if (incoming) return {...state, ...incoming, specialKey: 
       processSpecial(incoming.specialKey)}
   return state

以下是可用于解决 redux-persist 的方法

   persistor.pause() - pauses redux persist
   persistor.resume() - resumes redux persist
   persistor.purge() - deletes all persisted data
   persistor.rehydrate() - calls reducer to rehydrate store

redux persist 允许的存储类型

// sessionStorage
import { persistStore } from 'redux-persist'
import { asyncSessionStorage } from 'redux-persist/storages'    
persistStore(store, {storage: asyncSessionStorage})

// react-native
import {AsyncStorage} from 'react-native'
persistStore(store, {storage: AsyncStorage})

// web with recommended localForage
import localForage from 'localforage'
persistStore(store, {storage: localForage})

这是redux-persist最基本的用法希望对你有帮助。

【讨论】:

    【解决方案2】:

    您可以将任意数量的组件连接到相同的存储属性 - 这不是问题。需要注意的是,connect 正在侦听更改,因此当操作更改存储时,它会导致所有侦听更改存储部分的组件重新渲染(或至少进行计算然后比较 shadowdom)。

    仅在运行应用程序时存储存储 - 在页面关闭/刷新后它被清除。

    关于存储持久性(例如到本地存储)有一个很好的线程:Where to write to localStorage in a Redux app?

    【讨论】:

      【解决方案3】:

      正如前面的答案中提到的,将状态存储在本地存储中是一种可能的解决方案,但其他一些可能的解决方案是

      1. 确保您的链接使用 Push API 即 <Link to={"route"}/> (react-router) 这将确保在路由更改之间不会删除存储

      2. 在创建商店时设置初始状态

      const rootReducer = combineReducers({
        todos: todos,
        visibilityFilter: visibilityFilter
      });
      
      const initialState = { 
        todos: [{id:123, text:'hello', completed: false}] 
      };
      
      const store = createStore(
        rootReducer, 
        initialState
      );

      这将在你的 reduce 存储初始化时为它补充水分

      1. 还有一些其他库/框架/样板,您可以使用它们也实现 服务器渲染 将在初始渲染时将 HTML 渲染到页面,然后在 DOM 加载一些内容后加载 React这个库是

      Next.js,Electroide,react-redux-universal-hot-example

      走这条路会大大增加您的应用程序的复杂性,因此您应该在走这条路之前权衡利弊

      【讨论】:

        【解决方案4】:

        我遇到了这个问题,所以正如这里有人提到的,我使用了 localStorage。

        在我的减速器中,我这样做了:

        const exampleKey = "_exampleKey"
        
        const INITIAL_STATE = {
            example: JSON.parse(localStorage.getItem(exampleKey))
        };
        
        export default (state = INITIAL_STATE, action) => {
            switch (action.type) {
                case 'SET_TRUE':
                    localStorage.setItem( exampleKey, JSON.stringify(true));
                    return { ...state, example: true  };
                case 'SET_FALSE':
                    localStorage.setItem( exampleKey, JSON.stringify(false));
                    return { ...state, example: false};
                default:
                    return state
        }

        INITIAL_VALUES.example 指向localStorage 的项目example 确保我们在页面重新加载时保持正确的值。

        希望它对某人有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-12-11
          • 1970-01-01
          • 2018-03-22
          • 2018-05-29
          • 2018-03-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多