React Redux 刷新问题

Posted

技术标签:

【中文标题】React Redux 刷新问题【英文标题】:React Redux Refresh issue 【发布时间】: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,无论你想要什么(并且适合媒体)。重点仍然存在 - 默认情况下,状态树无法自行重新加载页面,它需要保存在某个地方。 为什么不在这两个布局之上的层次结构中创建一个状态呢? 为什么不在这两个布局之上的层次结构中创建一个状态呢? How can I persist redux state tree on refresh?的可能重复 【参考方案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】:

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

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

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

const rootReducer = combineReducers(
  todos: todos,
  visibilityFilter: visibilityFilter
);

const initialState =  
  todos: [id:123, text:'hello', completed: false] 
;

const store = createStore(
  rootReducer, 
  initialState
);

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

    还有一些其他库/框架/样板,您可以使用它们也实现 服务器渲染 将在初始渲染时将 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 确保我们在页面重新加载时保持正确的值。

希望它对某人有所帮助。

【讨论】:

以上是关于React Redux 刷新问题的主要内容,如果未能解决你的问题,请参考以下文章

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

React + redux + axios + thunk,等待interceptors.response 刷新token

使用 React Native 和 Redux 刷新 OAuth 令牌

如何使用 redux 模式在 react native 中刷新组件?

使用 redux saga 在 react native 中实现令牌刷新

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