【React】如何监听LocalStorage的变化

在代码中遇到了需要在react中监听localStorage的数据,下意识想到的是按照useEffect监听useState变化那一套,但是未生效。

代码如下:

useEffect(()=>{
    console.log("变化了")
},[localStorage.getItem('data')])

需要使用监听器

useEffect(() => {
  function checkData() {
    const item = localStorage.getItem('data')

    if (item) {
      setData(item)
    }
  }

  window.addEventListener('storage', checkData)

  return () => {
    window.removeEventListener('storage', checkData)
  }
}, [])

但是上述方式有弊端,只能监听同源的两个页面之间的 storage 变更,没法监听同一个页面的变更。

需要自定义事件

const originalSetItem = localStorage.setItem
localStorage.setItem = function (key, newValue) {
  const setItemEvent = new Event("setItemEvent")
  setItemEvent[key] = newValue
  window.dispatchEvent(setItemEvent)
  originalSetItem.apply(this, [key, newValue])
}

// 添加事件监听器
function handleSetItemEvent(event) {
  console.log("监听到本地存储发生变化了:", event)
  console.log("Key:", Object.keys(event)[0])
  console.log("Value:", event[Object.keys(event)[0]])
}
window.addEventListener("setItemEvent", handleSetItemEvent)

// 当不再需要时,移除事件监听器
window.removeEventListener("setItemEvent", handleSetItemEvent)
useEffect(() => {
  // 重写localStorage.setItem方法,监听本地存储的变化
  const originalSetItem = localStorage.setItem
  localStorage.setItem = function (key, newValue) {
    const setItemEvent = new CustomEvent("setItemEvent", {
      detail: { key, newValue },
    })
    window.dispatchEvent(setItemEvent)
    originalSetItem.apply(this, [key, newValue])
  }

  const handleSetItemEvent = (event) => {
    const customEvent = event
    if (customEvent.detail.key === "trace_info") {
      const updatedTraceInfo = safeParse(customEvent.detail.newValue)
      console.log("监听到本地存储发生变化了:", updatedTraceInfo)
      处理逻辑...
    }
  }

  window.addEventListener("setItemEvent", handleSetItemEvent)

  // 清除事件监听器
  return () => {
    window.removeEventListener("setItemEvent", handleSetItemEvent)
    localStorage.setItem = originalSetItem // 还原本地存储原生方法
  }
}, [])

封装为可复用Hook,其中localStorageKey:本地存储的key,callback:监听到本地存储变化后的处理函数

import { useEffect } from "react"

function safeParse(jsonString) {
  if (jsonString === null) {
    return null
  }
  try {
    return JSON.parse(jsonString)
  } catch (error) {
    console.error("Error parsing JSON:", error)
    return null
  }
}

function useLocalStorageListener(localStorageKey, callback) {
  useEffect(() => {
    const originalSetItem = localStorage.setItem
    localStorage.setItem = function (key, newValue) {
      const setItemEvent = new CustomEvent("setItemEvent", {
        detail: { key, newValue },
      })
      window.dispatchEvent(setItemEvent)
      originalSetItem.apply(this, [key, newValue])
    }

    const handleSetItemEvent = (event) => {
      const customEvent = event
      if (event.detail.key === localStorageKey) {
        // 这里的key就是本地存储对应的key
        const updatedValue = safeParse(customEvent.detail.newValue)
        callback(updatedValue) // 将本地存储最新的值传给回调函数
      }
    }

    window.addEventListener("setItemEvent", handleSetItemEvent)

    return () => {
      window.removeEventListener("setItemEvent", handleSetItemEvent)
      localStorage.setItem = originalSetItem
    }
  }, [localStorageKey, callback])
}

export default useLocalStorageListener

使用该Hook,这里假设监听LocalStorage中key为「data」的数据,并在其变化时执行log。

useLocalStorageListener("data", (updatedTraceInfo) => {
	console.log("data最新值:",updatedTraceInfo)
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

田本初

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值