首页 > 其他分享 >单页应用刷新页面后状态保留的解决方案

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

时间:2025-01-04 17:55:50浏览次数:1  
标签:状态 const 单页 解决方案 MobX data store 页面

在使用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或服务器端存储可能更为合适。

标签:状态,const,单页,解决方案,MobX,data,store,页面
From: https://www.cnblogs.com/little-sheep10/p/18652147

相关文章

  • 解决方案 | aardio的plus控件实现无边框悬浮窗带按钮带置顶
    importfonts.fontAwesome;importwin.ui;/*DSG{{*/varwinform=win.form(text="aardioform";right=312;bottom=50;border="none";menu=false;title=false)winform.add(bkplus={cls="bkplus";left=2;top=5;right=205;bottom=46;backgro......
  • 成功接入国际OCPP平台的解决方案
    随着新能源汽车市场的快速增长,充电桩作为关键基础设施的重要性日益凸显。然而,不同品牌和地区的充电桩协议标准不统一,给互联互通和跨平台管理带来了巨大挑战。为解决这一问题,OCPP(OpenChargePointProtocol)协议成为行业标准,能够实现充电桩与中央管理系统(CSMS)之间的无缝通信。深圳......
  • uniapp:编译微信、h5都正常的,编译钉钉小程序无法找到页面
    我们在做uniapp的开发的时候遇到很多莫名其妙的问题,其中就有个很奇葩的问题,我们开发的过程中使用微信小程序/h5调试都是正常编译正常跳转,然后在要上架的时候,编译钉钉小程序成功,但是访问页面无法访问,Error:frameworkerror:cannotfindpage:pages/repairs/repairs-accept......
  • 解决方案 | aardio 右上角和托盘区的关闭按钮功能不同源代码
    importwin.ui;/*DSG{{*/varwinform=..win.form(text="aardioForm";right=599;bottom=399)winform.add()/*}}*/importwin.util.tray;vartray=win.util.tray(winform,"~\extensions\res\app.ico")//创建托盘图标,如果不能显示图标,可能是图标问题,要复合图标tray......
  • MybatisX-Generator不生成domain文件夹解决方案
    问题描述使用MybatisX-Generator生成数据库表实体以后,发现没有生成domain文件夹以及User.java文件问题原因以及解决方案因为MybatisX版本更新,最新版需要在options里额外勾选model才能生成domain勾选model,点击finish,成功生成domain文件夹,以及User.java文件......
  • 基于 GitHub API 的 Issue 和 PR 自动化解决方案
    文章目录摘要引言优化Issue和PR管理的方法工具选择流程优化自动化Issue和PR管理代码逻辑详解获取Issue数据为Issue添加标签将Issue分配给开发者主逻辑实际运行效果进一步扩展QA环节总结参考资料摘要在开源项目中,Issue和PullRequest(PR)的数量庞......
  • gozero实现对接开放平台分贝通中新建费用报销的sdk设计与解决方案
    使用GoZero框架来实现费用报销对接CRM系统的SDK设计和解决方案,可以分为以下几个步骤。GoZero是一个Go语言编写的高性能Web框架,具有丰富的功能,适用于构建API服务。下面是如何使用GoZero来实现费用报销管理系统的API,并与CRM系统对接的方案。###一、准备工作......
  • Creo许可管理的常见问题及解决方案
    随着工程设计的复杂性和软件使用的普及性增加,Creo许可管理成为了许多企业面临的挑战。本文将解答关于Creo许可管理的常见问题,并提供相应的解决方案,帮助企业更好地管理和利用Creo许可证。常见问题一:许可证分配不均问题描述:在某些情况下,企业可能会遇到许可证分配不均的问题,导致某......
  • 协同管理软件:销售行业的数据驱动解决方案
    引言销售行业的竞争日益激烈,企业需要不断寻找新的方法来提升团队的工作效率和业绩。协同管理软件通过提供一个集中的平台,使销售团队能够更好地管理客户信息、跟踪销售漏斗,并协作完成销售任务。本文将详细介绍协同管理软件的核心功能、如何应用于销售流程,以及如何通过这些工具提升......
  • 鸿蒙开发-阅读器正文页面实现
    鸿蒙开发-阅读器正文页面实现记录开发一个小说阅读应用的过程实现点击书籍,读取该书籍的文件内容,然后显示该书籍正文内容,滑动进行翻页。实现逻辑在书架页面,获取书籍列表,为每一项添加点击事件,进行路由带参跳转,参数为书籍路径或书籍URL,跳转到正文页面。进入正文页面后,设置阅读......