【问题标题】:useEffect does not listen for localStorageuseEffect 不监听 localStorage
【发布时间】:2020-07-25 10:37:12
【问题描述】:

我正在创建一个身份验证系统,在后端将我重定向到前端页面后,我正在为 userData 发出 API 请求,并将该数据保存到 localStorage。然后我尝试加载 Spinner 或 UserInfo。

我正在尝试使用 useEffect 监听 localStorage 值,但登录后我得到“未定义”。当 localStorage 值更新时,useEffect 不再运行,Spinner 一直在旋转。

我尝试过这样做:JSON.parse(localStorage.getItem('userData')),但后来我得到了一个 useEffect 无限循环。

只有当我刷新页面时,我的 localStorage 值才会出现,我可以显示它而不是 Spinner。

我做错了什么?

也许有更好的方法在准备好后加载 userData?

我正在尝试以正确的方式更新 DOM?

感谢您的回答;)

import React, { useState, useEffect } from 'react';
import { Spinner } from '../../atoms';
import { Navbar } from '../../organisms/';
import { getUserData } from '../../../helpers/functions';

const Main = () => {
  const [userData, setUserData] = useState();
  useEffect(() => {
    setUserData(localStorage.getItem('userData'));
  }, [localStorage.getItem('userData')]);

  return <>{userData ? <Navbar /> : <Spinner />}</>;
};

export default Main;

【问题讨论】:

    标签: javascript node.js reactjs react-hooks local-storage


    【解决方案1】:

    这里最好为localstorage添加一个事件监听器。

    useEffect(() => {
      function checkUserData() {
        const item = localStorage.getItem('userData')
    
        if (item) {
          setUserData(item)
        }
      }
    
      window.addEventListener('storage', checkUserData)
    
      return () => {
        window.removeEventListener('storage', checkUserData)
      }
    }, [])
    

    【讨论】:

    • 扩展这个答案:OPs 示例不起作用的原因是因为传递给 useEffect 的依赖数组确定在渲染组件时是否重新运行效果,这意味着虽然如果 localStorage 发生变化,效果会重新运行,它必须先渲染。解决这个问题的方法是像 Minan 一样设置对 localStorage 的订阅,以观察更改并通知组件重新渲染。
    • 嗨,你能帮我解决这个问题吗? stackoverflow.com/questions/62906923/…
    • this 怎么样?这不是说在改变存储的选项卡中不会触发 eventListener 吗?
    • 其实不是这样的。正如您在此示例演示中所见,所有值继续同步工作。演示 => mq4uu.csb.app 代码 => codesandbox.io/s/bold-rain-mq4uu
    • @Minan 我很难在项目中重现此逻辑,不知道为什么存储上的事件侦听器对 removeItem 事件没有反应,在您的沙箱中添加了第二个按钮:codesandbox.io/s/elegant-star-yw1z5
    【解决方案2】:
    • “也许有更好的方法在 userData 准备好后加载它?”

    您可以将值直接评估为 localStorage,而不是传递给 state。

    const Main = () => {
      if (localStage.getItem('userData')) {
        return (<Navbar />);
      }
      else {
        return (<Spinner />);
      }
    };
    

    如果需要在更多组件中检索 userData,请评估 Redux 对您的应用程序的实现,这可以消除 localStorage 的使用,但当然,这取决于您的需求。

    【讨论】:

    • 以这种方式捕获“未定义”值(并且微调器将永远旋转)。几秒钟后更新“未定义”值时,它不会更新 DOM。
    • 有趣...尝试将 userData 作为道具传递给 Main 组件。
    • 这会在每次重新渲染时将线程阻塞读入本地存储,所以要小心
    • @hakazvaka 使用 IndexedDB 可以解决这个问题吗?知道异步工作......
    【解决方案3】:

    解决方法是使用这个结构:

    useEffect(() => {
        window.addEventListener("storage", () => {
          // When storage changes refetch
          refetch();
        });
    
        return () => {
          // When the component unmounts remove the event listener
          window.removeEventListener("storage");
        };
    }, []);
    

    【讨论】:

      【解决方案4】:

      “存储”事件的事件侦听器无法在同一页面中工作

      当一个存储区域触发Window界面的存储事件 (localStorage) 已在另一个文档的上下文中进行了修改。

      https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event

      【讨论】:

        猜你喜欢
        • 2021-08-13
        • 1970-01-01
        • 2021-06-16
        • 2019-11-01
        • 2023-03-20
        • 2019-11-06
        • 2013-04-18
        • 2021-10-12
        • 1970-01-01
        相关资源
        最近更新 更多