【问题标题】:How do i re-run useEffect hook if the localstorage value has been changed?如果 localstorage 值已更改,我如何重新运行 useEffect 挂钩?
【发布时间】:2022-04-18 14:22:30
【问题描述】:

我正在尝试重新运行 useEffect 挂钩,具体取决于是否已将任何新项目添加到本地存储中。

我的 useEffect 看起来像这样:

useEffect(() => {
      //getting all localstorage items and setting to a variable
      const localStorageItems = { ...localStorage }

      // filtering out the localstorage items for keys that only starts with "HTTP" & pushing it to the state called "testData" using setTestData useState hook.
    
      const filteredByKey = Object.fromEntries(
        Object.entries(localStorageItems).filter(([key, value]) => {
          if (key.startsWith("http")) {
            testArr2.push({ urls: [key, value] })
            // setTestData({ urls: [key, value] })
            setTestData((prev) => [...prev, { key, value }])
          }
        })
      )
    }, [])

我的问题是当我点击按钮(添加新数据)时,这个 useEffect 应该理想地重新运行,将最新数据设置为“testData”状态。

问题:

  • 我无法将 window.localstorage 传递给 useEffect 的数组依赖列表,因为我相信它是外部变量,并且 react 不允许这样做。

我尝试过的:

  • 我在 SO 上查看了这个 answer,但我的情况有点复杂,因为我首先将整个项目加载到一个变量中(我不知道有什么更好的选择)
  • 我尝试将状态值放入依赖列表中,但它不起作用并进入无限循环。

请帮忙。 感谢您阅读本文。

【问题讨论】:

  • 您链接到的 SO 答案应该适用于您的情况。它只是为本地存储更改设置了一个侦听器(这是您想要的),并且仅在组件的第一次渲染时设置该侦听器(useState 的空依赖数组使其仅在第一次渲染时运行)。跨度>
  • ``` useEffect(() => { function checkUserData() { const localStorageItems = { ...localStorage } if (localStorageItems) { const filtersByKey = Object.fromEntries( Object.entries(localStorageItems) .filter(([key, value]) => { if (key.startsWith("http")) { testArr2.push({ urls: [key, value] }) // setTestData({ urls: [key, value ] }) setTestData((prev) => [...prev, { key, value }]) } }) ) }}window.addEventListener("storage", checkUserData) }, []) ```
  • @elunomas 我按照上面的方法做了,但它甚至没有渲染一段时间
  • 你能分享更多你的代码吗?如果包含空的依赖数组,useEffect 挂钩将在第一次渲染时运行 1 次。 (reactjs.org/docs/…) 如果您的代码甚至没有渲染一次,那么您需要分享更多代码,然后我们才能说出问题所在。

标签: javascript reactjs local-storage use-effect


【解决方案1】:

我可以为您提供解决此用例的方法,创建与 localStorage 同步的反应上下文。您可以将上下文用作useEffect 依赖项。同步意味着,在启动时从localStorage 中获取值,并从您的应用程序中与localStorage 一起更新上下文。

【讨论】:

    【解决方案2】:

    定义一个保存本地存储值的状态并将其作为 useEffect 参数传递。

    const [localStorageData, setLocalStorageData] = useState([]);
    
    useEffect(() => {
    
        // Your codes
    
    }, [localStorageData])
    

    【讨论】:

    • 这不起作用,我需要为此重新触发const localStorageItems = { ...localStorage },但我该怎么做(同样的问题)
    • anshul 如果您在代码中更新本地存储的任何地方实现了 setLocalStorageData,这可能对您有用。但是@Serkan,虽然这可能有效,但创建一个 localstorage 的副本只是为了观察 localstorage 的变化似乎是多余的,不是吗?然后 anshul 将需要在本地存储被修改的任何地方编写 set 函数。一个更简洁的解决方案就是为 localstorage 设置一个事件侦听器来更改,就像问题中已经链接到的 SO 答案一样。
    【解决方案3】:

    您可以使用“存储”事件监听器

    window.addEventListener('storage', function(e) {
      if (e.newValue) {
        console.log('new data is saved ...')
        // ...... your code
      }
    })
    

    【讨论】:

      猜你喜欢
      • 2022-01-26
      • 1970-01-01
      • 1970-01-01
      • 2022-11-22
      • 2020-07-24
      • 1970-01-01
      • 1970-01-01
      • 2021-02-13
      • 2022-11-17
      相关资源
      最近更新 更多