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

And*_*Kid 4 javascript reactjs react-router react-redux

我是新来的反应js。

我有两条路线,例如A和B。现在我将一些值从A传递给B作为道具。如果刷新了B页面,则来自A的所有道具值都将消失,并且B页面不会呈现。我正在使用redux反应。

mapDispatchToPropsmapStateToProps函数用于在A和B路线之间传递值作为道具。

例如:路线A进行了一些计算,并将值存储在redux状态,路线B导出为connect(mapStateToProps, mapDispatchToProps)(B),通过使用mapStateToProps,状态A的状态值作为prop传递给B。

请建议我在上述用例上处理浏览器刷新的最佳方法,以及在路由之间传递值的其他最佳方法。提前致谢。

Shi*_*hir 5

您的问题涉及两个不同的问题。首先是在React / Redux应用程序中将道具从一个页面传递到另一个页面,其次是刷新页面时保持应用程序状态。

您已经描述了在基于Redux的应用程序中在两条路由之间传递数据的正确方法。

这把我们带到了第二个问题。
刷新页面时如何维护React / Redux应用程序的状态?

刷新React / Redux应用程序后,它将再次初始化,并且Redux存储将获取其默认值。

如果希望在页面刷新或不同会话之间保持应用程序状态,则需要将状态存储在某个地方,并在应用程序初始化时加载它。

我们可以将这个问题分为三个部分:

  • 数据存储在哪里
  • 如何存储Redux状态
  • 初始化应用程序时如何重新加载数据

让我们分别查看每个子问题。

数据存储在哪里?

您可以使用Web Storage API在用户的浏览器中存储数据。该API提供了两种存储数据的机制:

  • sessionStorage:只要打开浏览器,存储的数据就会保留,包括页面重新加载和还原。
  • localStorage:保留数据,直到被用户或应用程序清除为止。即使关闭并重新打开浏览器,它仍然存在。

双方的sessionStoragelocalStorage的让你键值对存储在浏览器中,并且都提供相同的功能集来管理数据。

对于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();
Run Code Online (Sandbox Code Playgroud)

对于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');
Run Code Online (Sandbox Code Playgroud)

如何存储redux状态?

如您所知,Redux提供了一个使用createStore我们的root reducer并返回application 的函数store

所述存储对象包含整个应用商店,并且提供了一些方法,包括一个注册的监听器。

store.subscribe(listener) 可用于向商店添加更改侦听器,每次商店更新时都会调用该侦听器。

我们将在存储中添加一个侦听器,这会将应用程序状态保存到localStorage

尝试使用以下命令将其添加到创建商店的文件中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());
});
Run Code Online (Sandbox Code Playgroud)

再次初始化应用程序时,如何重新加载存储的数据并恢复应用程序状态?

当我们使用创建应用商店时createStore,我们可以选择使用函数的第二个参数将初始状态传递给商店。

当应用程序启动时,我们将检查中localStorage是否有保存的数据。如果找到它,则将其作为第二个参数发送给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);
Run Code Online (Sandbox Code Playgroud)

而已!现在,结合最后两个代码块,您的应用程序就能够在页面刷新甚至浏览器重启之间保持状态。

希望这可以帮助。干杯! :)


Sri*_* Sg 0

尝试使用react-router,这将渲染基于route.

当应用程序处于 状态时initialized,应用程序应该获取数据并使用所需信息更新商店。

例如:在下面的示例中,当IntilizeApp组件安装时计算所需的信息并通过分派操作来更新存储。componentWillMount像计算一样使用react的生命周期方法。

    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>
Run Code Online (Sandbox Code Playgroud)