localStorage 适用于桌面设备,但不适用于移动设备(iOS 版本 12.2)

2023-12-14

我使用 React 创建了一个简单的 Todos 应用程序,并实现了localStorage为了在页面刷新之间保留数据。实现是这样的:

loadStateFromLocalStorage() {
  for (let key in this.state) {
    if (localStorage.hasOwnProperty(key)) {
      let value = localStorage.getItem(key);

      try {
        value = JSON.parse(value);
        this.setState({ [key]: value });
      } catch (e) {
        // handle empty string
        this.setState({ [key]: value });
      }
    }
  }
}
saveStateToLocalStorage() {
  for (let key in this.state) {
    localStorage.setItem(key, JSON.stringify(this.state[key]));
  }
}

如果需要,我的完整 App.js 在这里(代码托管在 GitHub 上)here):

import React, { Component } from 'react';
import './App.css';
import Search from './components/Search.js';
import Todos from './components/Todos.js';
import Filters from './components/Filters.js';
import { TodoFilter, InitialState } from './common';
import GitHubIcon from './components/GitHubIcon.js'


class App extends Component {

  state = InitialState;

  // Local Storage
  loadStateFromLocalStorage() {
    for (let key in this.state) {
      if (localStorage.hasOwnProperty(key)) {
        let value = localStorage.getItem(key);

        try {
          value = JSON.parse(value);
          this.setState({ [key]: value });
        } catch (e) {
          // handle empty string
          this.setState({ [key]: value });
        }
      }
    }
  }
  saveStateToLocalStorage() {
    for (let key in this.state) {
        localStorage.setItem(key, JSON.stringify(this.state[key]));
    }
  }

  // Lifecycle methods
  componentDidMount() {
    // Load state from localStorage
    this.loadStateFromLocalStorage();

    // Resizing page
    this.setState({width: window.innerWidth});
    window.addEventListener("resize", this.updateDimensions);

    // Set localStorage on refresh/reload
    window.addEventListener(
      "beforeunload",
      this.saveStateToLocalStorage.bind(this)
    );
  }
  componentWillUnmount() {
    // Remove listeners
    window.removeEventListener(
      "beforeunload",
      this.saveStateToLocalStorage.bind(this)
    );
    window.removeEventListener("resize", this.updateDimensions);

    // Save state to localStorage
    this.saveStateToLocalStorage();
  }

  updateDimensions = () => {
    this.setState({ 
      width: window.innerWidth
    });
  }

  // Add a new Todo
  handleSubmit = (event) => {
    event.preventDefault();
    if(this.state.currentTodoText !== "") {
      const newTodo = {
        id: Date.now(),
        text: this.state.currentTodoText,
        checked: false
      };
      const todos = [...this.state.todos, newTodo];
      this.setState({todos});
      this.setState({currentTodoText: ""});
      document.querySelector(".search input").value = "";
    }
  }

  // Update current Todo text
  handleChange = (event) => this.setState({currentTodoText: event.target.value})

  resetData = (event) => {
    event.preventDefault();
    this.setState({todos: InitialState.todos});
    this.setState({currentTodoText: InitialState.currentTodoText});
    this.setState({currentFilter: InitialState.currentFilter});
    document.querySelector(".search input").value = "";
  }

  // Delete a Todo
  handleDelete = (todo) => {
    const todos = this.state.todos.filter((td) => td.id !== todo.id)
    this.setState({todos})
  }

  // Check a Todo
  handleCheck = (todo) => {
    const todos = this.state.todos.map((td) => td.id === todo.id ? {...td, checked: !td.checked} : td)
    this.setState({todos})
  }

  // Change Todo filter
  handleFilter = (filter) => {
    switch (filter) {
      case TodoFilter.filterCompleted: {
        this.setState({currentFilter: TodoFilter.filterCompleted})
        break;
      }
      case TodoFilter.filterUncompleted: {
        this.setState({currentFilter: TodoFilter.filterUncompleted})
        break;
      }
      case TodoFilter.all: {
        this.setState({currentFilter: TodoFilter.all})
        break;
      }
      default: {
        this.setState({currentFilter: TodoFilter.all})
        break;
      }
    }
  }

  render() {
    return (
      <div className="App">
        <Search handleChange={this.handleChange} handleSubmit={this.handleSubmit} resetData={this.resetData}/>
        <Filters handleFilter={this.handleFilter} currentFilter={this.state.currentFilter}/>
        <Todos todos={this.state.todos.filter(
          (todo) => {
            switch (this.state.currentFilter) {
              case TodoFilter.filterCompleted: return todo.checked;
              case TodoFilter.filterUncompleted: return !todo.checked;
              case TodoFilter.all: return true;
              default: return true;
            }
          }
        )} handleDelete={this.handleDelete} handleCheck={this.handleCheck}/>
        <GitHubIcon />
      </div>
    );
  }
}

export default App;

This works on desktop, but I hosted the app on Heroku[1] to see if it works on mobile too and data isn't persisting through page refreshes. Does localStorage work differently on mobile vs desktop? How do I implement localStorage to work both on my phone and my desktop?


[1] Since I tested the accepted answer by redeploying the app to Heroku, the link previously here no longer runs off the code which contained my issue and thus I've removed it - See the commit which fixed my issue here.


我发现了问题,beforeunloadSafari Mobile 不支持此活动。 看这个文档事件/卸载前

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

localStorage 适用于桌面设备,但不适用于移动设备(iOS 版本 12.2) 的相关文章

随机推荐

  • 将哈希表值属性导出到 CSV 文件

    我正在运行Test AdfsServerHealth Ref 问题是 输出值之一 值名称Output 是一个数组 显示为System Collection Hashtable我正在尝试找到一种方法以简洁的 Excel 格式获取此内容 例如
  • Android:将 ListVIew 中的项目居中

    我刚刚开始学习Android 想到了一个简单的项目来帮助我学习 我在 LinearLayout 上使用 ListView 创建了一个简单的菜单 我想要做的是将 ListView 中的文本居中 并将 ListView 放在布局中居中 我尝试将
  • 使用 CSS 旋转内联元素

    我意识到已经有很多这样的问题了 但我似乎无法让它们为我工作 因为大多数解决方案都针对 第 n 个孩子 或 以我极其 新手 的技能 我只是不明白它是如何工作的 我正在尝试为一项任务制作一个 交易或不交易 游戏 我花了太多时间让它看起来不错 这
  • WPF控件创建过程的步骤

    我已经寻找这样的解释有一段时间了 但我还没有找到任何解释 问题是我想知道 Wpf 控件的初始化 创建过程的步骤 让我们看一个简单的按钮 我想知道当调用构造函数时发生了什么 何时将控件添加到视觉树 逻辑树 何时调用依赖属性值 何时调用Appl
  • Phonegap触摸事件

    我的问题是我想从首页 index html 播放音频 视频文件 它的工作原理是这样的 function setaudio aud prepend a href img src icons audio file png alt Audioda
  • 删除存储在数组中的特定类对象[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 我的代码有问题 我想知道是否有人可以看一下 我创建了一
  • 如何为旧的 Angular 项目提供服务?

    我试图ng serve第三方框架中包含的 Angular 示例项目 从其示例项目来看 它需要 Angular v 4package json文件 我的全局 CLI 版本是 6 0 8 该项目不包括node modules文件夹也不是angu
  • 将 PList 中的数据获取到 UITableView 中?

    我想维护一个记录列表 对于每条记录 我都维护相同类型的数据 我想在两个不同的地方使用这些数据 UITableView从每条记录中获取 名称 值 UIViewController这需要所有数据在不同领域使用 我认为我应该使用 plist 来存
  • 删除值时输入掩码不起作用

    我构建了一个函数来在键入时屏蔽输入 它工作正常 但是当删除输入中的值时 屏蔽的行为很奇怪 function App const phone setPhone React useState function maskPhone target
  • 替换dom元素中的所有字符串

    我有一个像这样的 DOM table style display none tr td td tr table
  • 使用 matplotlib 颜色图进行颜色循环

    如果我通过以下方式创建颜色 import numpy as np from matplotlib import pyplot as plt n 6 color plt cm coolwarm np linspace 0 1 0 9 n co
  • 在双精度数组上使用 unordered_map

    我的主要数据对象是一个双精度数组 其长度取决于我的类的特定实例 我想构造一个非常简单的哈希表来存储 检索这些对象 并且我们可以假设这些数字是以没有数字错误的方式生成的 int main std tr1 unordered map
  • 使用 Java 原子类进行模块化增量

    令我惊讶的是 Java 的 AtomicInteger 和 AtomicLong 类没有模块化增量的方法 以便在达到限制后值回绕到零 我想我一定错过了一些明显的东西 最好的方法是什么 例如 我想在线程之间共享一个简单的 int 并且我希望每
  • 在javascript中获取primefaces widgetVar并更新它

    我有一个像这样的 primefaces 组件
  • 释放临时过期的配置

    抱歉我的英语不好 但我是意大利人 我必须发布一个只能在少数设备上运行的应用程序 当配置文件过期时我应该做什么 该应用程序会继续工作吗 还是我应该使用更新后的配置文件再次发布它 thx all 不 该应用程序在 mobileprovision
  • 将带有 NULL entres 的列表转换为 R 中的 data.frame

    我有一个名为z z lt list list a 1 b 2 list a 2 b 3 list a NULL b 4 我希望将其转换为带有相应的 data framea条目在data frame分配为NULL 这样做 do call rb
  • Unobtrusive Ajax 在将 jQuery 更新到 1.9.0 后停止工作

    我刚刚将 jQuery 和 jQuery UI 更新为 jquery 1 9 0 min js 和 jquery ui 1 9 2 min js 而且 我所有不显眼的 Ajax 调用 Ajax ActionLink Ajax BeginFo
  • 从 pom.xml 为现有 Maven 项目创建 WAR 文件

    我正在创建一个 Web 项目 有人告诉我它必须驻留在现有 Maven 项目的资源目录中 这是项目的结构 MavenProject src main resources My Web Project META INF MANIFEST MF
  • 处理XSS的方法(最佳实践)是什么?

    我正在使用 ASP NET 并且 ASP NET 页面上有 validate 属性 用于检查 XSS 验证 但我想知道这真的足够吗 我访问了 stackoverflow 上的一些相关帖子 这对我有帮助 但我想了解在开发网站时如何规划 XSS
  • localStorage 适用于桌面设备,但不适用于移动设备(iOS 版本 12.2)

    我使用 React 创建了一个简单的 Todos 应用程序 并实现了localStorage为了在页面刷新之间保留数据 实现是这样的 loadStateFromLocalStorage for let key in this state i