【问题标题】:Change in localstorage not triggering event listener本地存储中的更改未触发事件侦听器
【发布时间】:2020-07-14 22:11:44
【问题描述】:

我有 React 组件。最初我在 UseEffect 中设置了一些 localStorage。此外,我添加了事件侦听器。单击文本后,它会更改 localStorage 值,但事件侦听器没有触发,为什么?

import React, { useEffect } from "react";

export default function App() {

  useEffect(() => {
    window.localStorage.setItem("item 1", 'val 1');
    window.addEventListener('storage', () => {
      alert('localstorage changed!')
    })
  }, []);

  const getData = () => {
    localStorage.setItem("item", "val chamged");
  };

  return (
    <div className="App">
      <h1 onClick={getData}>Change localstorage value</h1>

    </div>
  );
}

https://codesandbox.io/s/naughty-engelbart-90tkw

【问题讨论】:

  • 请更新您的代码框,使其与您在此处粘贴的代码相同。您的链接沙箱中没有事件侦听器。
  • 如果您更改沙箱代码以匹配您在此处拥有的代码,特别是 onClick={getData} 部分,您将看到它有效。在调用 getData() 函数并传递结果而不是传递函数本身时存在拼写错误。
  • 已更新,但仍无法正常工作
  • useEffect() 无法检测到更改。我尝试了一些随机哈希来触发 useEffect codesandbox.io/s/serene-hawking-hz6pq 但仍然不知道为什么监听器什么都不做

标签: javascript reactjs local-storage


【解决方案1】:

有两件事不对。

  1. 更改onClick={getData()} onClick={getData}
  2. 来自文档 (https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event)。 The storage event of the Window interface fires when a storage area (localStorage or sessionStorage) has been modified in the context of another document. 请注意最后一句话,它不会在同一个文档中被解雇。您可以看到,如果您在同一浏览器中的 2 个标签页中打开 https://codesandbox.io/s/spring-browser-89con,就会开始出现警报。

【讨论】:

  • 谢谢,当在同一个文档中进行更改时,您知道如何修复它以使其正常工作吗?
  • 同一文档中不需要。您不能在更新 localStorage 后手动调用处理程序函数。 ?可能会编写一个包装函数来设置本地存储并调用您的回调。
【解决方案2】:

当窗口的存储区域发生变化时触发Storage事件。

注意:存储事件仅在窗口时触发 自己进行更改。

您可以查看更多详细信息和演示:storage Event

storage 事件处理程序只会影响其他窗口。每当localStorage 内的一个窗口发生变化时,所有其他窗口都会收到通知,如果需要采取任何措施,可以通过监听storage 事件的处理函数来实现。

【讨论】:

    【解决方案3】:

    试试这个 onclick 处理程序

    import React, { useEffect } from "react";
    
    export default function App() {
    
      useEffect(() => {
        window.localStorage.setItem("item 1", 'val 1');
        window.addEventListener('storage', () => {
          alert('localstorage changed!')
        })
      }, []);
    
      const getData = () => {
        localStorage.setItem("item", "val chamged");
      };
    
      return (
        <div className="App">
          <h1 onClick={()=>getData()}>Change localstorage value</h1>
    
        </div>
      );
    }
    

    【讨论】:

    • onClick={()=&gt;getData()}onClick={getData} 相同
    • 小斌,如果不需要,最好不要创建多余的匿名函数。
    【解决方案4】:

    我会提出一个解决方案。这可能是一个丑陋的解决方案,但它是我发现从同一个窗口实现它的唯一解决方案。 (由于某些原因,我需要更改 :))

    我使用了 MutationObserver 类,例如获取暗模式值的任何更改:

    const setTheme = (value) => {
        let htmlClasses = document.querySelector('html').classList
        if (value == true) {
            htmlClasses.add('dark');
        } else {
            htmlClasses.remove('dark');
        }
        window.localStorage.setItem('dark', value)
    }
    

    这里我在每次激活切换按钮时添加一个类,然后我在 html 类上配置一个观察者,如下所示:

    var observer = new MutationObserver(function (mutations) {
      mutations.forEach(function (mutation) {
          console.log(mutation);
          if (mutation.attributeName == "class") {
             // Do what you want here
          }
      });
    });
    var config = {
      attributes: true
    };
    
    observer.observe(document.querySelector('html'), config);
    

    您还可以查看我在 github here 上找到的另一个示例(对您更有用)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-27
      • 2019-05-14
      • 2013-05-19
      • 1970-01-01
      • 2020-05-09
      • 2020-09-06
      • 2021-01-14
      相关资源
      最近更新 更多