简体   繁体   English

如何跨页面刷新维护React / Redux应用程序的状态?

[英]How to maintain the state of React/Redux application across page refreshes?

I am new to react js. 我是新来的反应js。

I have two routes like A & B. Now i am passing some values from A to B as props. 我有两条路线,如A和B.现在我将一些值从A传递给B作为道具。 If B page is refreshed, then all props values from A is gone and B page is not rendering. 如果刷新B页面,则A中的所有道具值都将消失,B页面不会呈现。 I am using react with redux. 我正在使用与redux的反应。

mapDispatchToProps & mapStateToProps functions are used to pass values between A & B routes as props. mapDispatchToPropsmapStateToProps函数用于将A和B路由之间的值作为props传递。

For example: Route A has done some calculations and store the values in redux state and Route B is exported as connect(mapStateToProps, mapDispatchToProps)(B) , by using mapStateToProps in which A's state values are passed to B as props. 例如:路由A已完成一些计算并将值存储在redux状态,路由B通过使用mapStateToProps导出为connect(mapStateToProps, mapDispatchToProps)(B) ,其中A的状态值作为props传递给B。

Please suggest me the best way to handle browser refresh on above mentioned use case and also if any other best way to pass the values between routes. 请建议我在上述用例上处理浏览器刷新的最佳方法,以及在路由之间传递值的任何其他最佳方法。 Thanks in advance. 提前致谢。

Your question talks about two different concerns. 您的问题涉及两个不同的问题。 First is passing props from one page to another in a React/Redux application, and second is maintaining the application state when the page is refreshed. 首先是在React / Redux应用程序中将props从一个页面传递到另一个页面,其次是在刷新页面时维护应用程序状态。

You've described the correct method of passing data between two routes in a redux based application. 您已经描述了在基于redux的应用程序中在两个路由之间传递数据的正确方法。

Which brings us to the second concern. 这让我们想到了第二个问题。
How to maintain the state of a React/Redux application when the page is refreshed? 刷新页面时如何维护React / Redux应用程序的状态?

When a React/Redux application is refreshed, it gets initialised again and the redux store gets it's default values. 当刷新React / Redux应用程序时,它会再次初始化并且redux存储获取它的默认值。

If you wish to maintain the app state across page refreshes or across different sessions, you need to store the state somewhere, and load it when the app initialises. 如果您希望跨页刷新或跨不同会话维护应用程序状态,则需要将状态存储在某个位置,并在应用程序初始化时加载它。

We can divide this problem into three parts: 我们可以将这个问题分为三个部分:

  • Where to store the data 存储数据的位置
  • How to store redux state 如何存储redux状态
  • How to reload the data when the application is initialised 初始化应用程序时如何重新加载数据

Let's look at each sub-problem individually. 让我们分别看一下每个子问题。

Where to store the data? 存储数据的位置?

You can use the Web Storage API to store data within the user's browser. 您可以使用Web Storage API在用户的浏览器中存储数据。 This API provides 2 mechanisms to store data: 此API提供了2种存储数据的机制:

  • sessionStorage: Stored data is preserved as long as the browser is open, including page reloads and restores. sessionStorage:只要浏览器处于打开状态,就会保留存储的数据,包括页面重新加载和恢复。
  • localStorage: Data is preserved until it is cleared by the user or the application. localStorage:数据一直保留,直到用户或应用程序清除为止。 It persists even if the browser is closed and reopened. 即使浏览器已关闭并重新打开,它仍然存在。

Both sessionStorage and localStorage allow you to store key-value pairs in the browser, and both provide the same set of functions to manage data. sessionStoragelocalStorage都允许您在浏览器中存储键值对,并且两者都提供相同的功能集来管理数据。

For sessionStorage (example taken from MDN): 对于sessionStorage(从MDN获取的示例):

// Save data to sessionStorage
window.sessionStorage.setItem('key', 'value');

// Get saved data from sessionStorage
var data = window.sessionStorage.getItem('key');

// Remove saved data from sessionStorage
window.sessionStorage.removeItem('key');

// Remove all saved data from sessionStorage
window.sessionStorage.clear();

For localStorage: 对于localStorage:

// Save data to localStorage
window.localStorage.setItem('key', 'value');

// Get saved data from localStorage
var data = window.localStorage.getItem('key');

// Remove saved data from localStorage
window.localStorage.removeItem('key');

How to store redux state? 如何存储redux状态?

As you are already aware, Redux provides a createStore function which takes our root reducer and returns the application store . 您已经知道,Redux提供了一个createStore函数,该函数使用root reducer并返回应用程序store

The store object holds the entire application store, and provides a few methods including one to register a listener. store对象包含整个应用程序商店,并提供一些方法,包括一个注册监听器的方法。

store.subscribe(listener) can be used to add a change listener to the store, which will get called every time the store gets updated. store.subscribe(listener)可用于向商店添加更改侦听器,每次商店更新时都会调用该更改。

We will add a listener to the store, which will save the application state to localStorage . 我们将向商店添加一个监听器,它将应用程序状态保存到localStorage

Try adding this in the file where you create your store using createStore : 尝试使用createStore在您创建商店的文件中添加:

/**
 * This function accepts the app state, and saves it to localStorage
 * @param state
 */
const saveState = (state) => {
    try {
        // Convert the state to a JSON string 
        const serialisedState = JSON.stringify(state);

        // Save the serialised state to localStorage against the key 'app_state'
        window.localStorage.setItem('app_state', serialisedState);
    } catch (err) {
        // Log errors here, or ignore
    }
};

/**
 * This is where you create the app store
 */
const store = createStore(rootReducer);

/**
 * Add a change listener to the store, and invoke our saveState function defined above.
 */
store.subscribe(() => {
    saveState(store.getState());
});

How to reload the stored data, and restore the application state when the app is initialised again? 如何重新加载存储的数据,并在应用程序再次初始化时恢复应用程序状态?

When we create our app store using createStore , we have the option to pass an initial state to the store using the second parameter to the function. 当我们使用createStore创建我们的应用商店时,我们可以选择使用函数的第二个参数将初始状态传递给商店。

When the application starts up, we will check the localStorage for any saved data. 当应用程序启动时,我们将检查localStorage是否有任何已保存的数据。 If we find it, we will send it as the second parameter to createStore . 如果我们找到它,我们将把它作为createStore的第二个参数发送。

This way, when the app finishes initialising, it will have the same state as it did before the page was refreshed or the browser was closed. 这样,当应用程序完成初始化时,它将具有与刷新页面或关闭浏览器之前相同的状态。

Try adding this in the file where you create your store using createStore : 尝试使用createStore在您创建商店的文件中添加:

/**
 * This function checks if the app state is saved in localStorage
 */
const loadState = () => {
    try {
        // Load the data saved in localStorage, against the key 'app_state'
        const serialisedState = window.localStorage.getItem('app_state');

        // Passing undefined to createStore will result in our app getting the default state
        // If no data is saved, return undefined
        if (!serialisedState) return undefined;

        // De-serialise the saved state, and return it.
        return JSON.parse(serialisedState);
    } catch (err) {
        // Return undefined if localStorage is not available, 
        // or data could not be de-serialised, 
        // or there was some other error
        return undefined;
    }
};

/**
 * This is where you create the app store
 */
const oldState = loadState();
const store = createStore(rootReducer, oldState);

That's it! 而已! Now, combine the last two blocks of code, and your application has the ability to maintain state across page refreshes, or even across browser restarts. 现在,结合最后两个代码块,您的应用程序可以跨页面刷新维护状态,甚至可以跨浏览器重新启动。

Hope this helps. 希望这可以帮助。 Cheers! 干杯! :) :)

你可以尝试redux-persistredux-storage ,当初始化存储createStore(reducer, [preloadedState], [enhancer]) ,你可以获取数据并将其分配给preloadedState

Try using react-router and this will render components based on route . 尝试使用react-router ,这将基于route呈现组件。

When the app is initialized , app should fetch data and update the store with the required information. initialized应用程序时,应用程序应获取数据并使用所需信息更新商店。

Eg: In the below example, When IntilizeApp component is mounting compute the information required and update the store by dispatching the actions. 例如:在下面的示例中,当IntilizeApp组件正在装载时,计算所需的信息并通过调度操作来更新存储。 Use react's life cycle method like componentWillMount to compute. 使用react的生命周期方法,如componentWillMount来计算。

    import {Router, Route, hashHistory} from 'react-router'
    // import initializeApp
    // import ComponentA
    // import ComponentB

    <Router history={hashHistory}>
      <Route path="/" component={InitializeApp}>
        <Route name="A" path="A" component={ComponentA} />
        <Route name="B" path="B" component={ComponentB} />
      </Route>
    </Router>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM