单页应用刷新页面后状态保留的解决方案

在使用React框架构建单页应用时,页面刷新后状态丢失是一个常见的问题。对于使用MobX作为状态管理的单页应用,解决这一问题尤为关键。以下是几种可行的解决方案:

一、浏览器本地存储

1. localStorage/sessionStorage

localStorage是浏览器提供的一种持久化存储方式,可以将状态数据保存在客户端,即使页面刷新或关闭浏览器,数据依然存在。sessionStorage与localStorage类似,但其数据仅在当前会话中有效,关闭浏览器标签页后数据会被清空。使用这两个storage进行状态持久化的步骤如下:

  • 页面刷新前保存状态数据:在页面即将刷新时,将MobX store中的状态数据序列化为JSON字符串,并存储到localStorage/sessionStorage中。
    import React from 'react';
    import { observer } from 'mobx-react';
    import { observable, action, computed, useStrict } from 'mobx';
    
    class Store {
    
        @observable data = {};
        @action getDataFromSessionStorage = () => {
            let data;
            const dataStr = sessionStorage.getItem('mobxState');
            if (!dataStr) {
                data = {};
            } else {
                data = JSON.parse(dataStr);
            }
            this.data = data;
        }
    
        @action onChange = (data) => {
            this.data = data;
            this.setDataToSessionStorage(data);
        }
    
        @action setDataToSessionStorage = (data) => {
            const dataStr = JSON.stringify(data);
            sessionStorage.setItem('mobxState', dataStr);
        }
    }
    
    let i = 0;
    
    const store = new Store();
    
    @observer
    export default class Test extends React.Component {
    
        componentDidMount() {
            store.getDataFromSessionStorage();
        }
    
        render() {
            const { data, onChange } = store;
            return (
                <div>
                    <p>{JSON.stringify(data)}</p>
                    <button onClick={() => onChange({ key: i++, data: Math.random() })}>change</button>
                </div>
            );
        }
    }
     

二、MobX Persist Store

MobX Persist Store是一个轻量级的工具,专门用于将MobX store中的观测值持久化到浏览器的本地存储中,并在页面重新加载后自动恢复。使用MobX Persist Store的步骤如下:

  • 安装MobX Persist Store
    yarn add mobx-persist-store
    # 或者
    npm i mobx-persist-store
  • 在MobX store中使用makePersistable
    import { makeAutoObservable } from 'mobx';
    import { makePersistable } from 'mobx-persist-store';
    
    export class SampleStore {
      someProperty = [];
      constructor() {
        makeAutoObservable(this);
        makePersistable(this, {
          name: 'SampleStore',
          properties: ['someProperty'],
          storage: window.localStorage,
        });
      }
    }
    在这个例子中,makePersistable会自动处理store的持久化和恢复工作。

三、React Router和React Context结合使用

如果你的单页应用使用了React Router,可以结合React Context来管理一些全局状态。通过Context提供者提供全局状态,并在整个应用中共享。这样,在页面刷新时,Context中的状态仍然存在:

  • 创建Context和Provider
    import { createContext, useContext } from 'react';
    const AppContext = createContext();
    export const AppProvider = ({ children }) => {
      const appStore = useStore();
      return <AppContext.Provider value={appStore}>{children}</AppContext.Provider>;
    };
    export const useAppStore = () => useContext(AppContext);
  • 在应用的顶层组件中使用AppProvider
    import { AppProvider } from './path-to-your-context-file';
    const App = () => {
      return (
        <AppProvider>
          {/* 其他组件 */}
        </AppProvider>
      );
    };
    export default App;
  • 在需要访问全局状态的组件中使用useAppStore
    import { useAppStore } from './path-to-your-context-file';
    const MyComponent = () => {
      const appStore = useAppStore();
      // 使用appStore中的状态
    };

四、IndexedDB

IndexedDB是一个更高级的浏览器存储方案,适合存储大量结构化数据。使用IndexedDB进行状态持久化的步骤如下:

  • 创建和打开数据库
    const openRequest = indexedDB.open('myDatabase', 1);
    openRequest.onupgradeneeded = (event) => {
      const db = event.target.result;
      db.createObjectStore('stateStore');
    };
  • 保存状态数据到IndexedDB
    const saveStateToDB = (state) => {
      const transaction = db.transaction(['stateStore'], 'readwrite');
      const store = transaction.objectStore('stateStore');
      store.put(state, 'mobxState');
    };
  • 从IndexedDB恢复状态数据
    const loadStateFromDB = () => {
      const transaction = db.transaction(['stateStore'], 'readonly');
      const store = transaction.objectStore('stateStore');
      const request = store.get('mobxState');
      request.onsuccess = () => {
        const state = request.result;
        mobxStore = new MobXStore(state);
      };
    };

五、服务器端存储

将状态数据保存到服务器端数据库中,也是一种可行的持久化方案。在页面刷新前,将状态数据发送到服务器进行存储;在页面加载时,从服务器获取状态数据并恢复:

  • 页面刷新前发送状态数据到服务器
    window.addEventListener('beforeunload', () => {
      fetch('/save-state', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(mobxStore),
      });
    });
  • 页面加载时从服务器获取状态数据
    fetch('/get-state')
      .then((response) => response.json())
      .then((state) => {
        mobxStore = new MobXStore(state);
      });

以上几种方案各有优缺点,可以根据实际需求和应用规模选择合适的方法。对于简单的应用,使用localStorage或MobX Persist Store可能更方便快捷;而对于需要存储大量数据或需要跨设备同步的应用,IndexedDB或服务器端存储可能更为合适。

posted @ 2025-01-04 17:47  Yang9710  阅读(304)  评论(0)    收藏  举报