簡體   English   中英

使用跨不同組件的自定義掛鈎反應、更新和檢測 localStorage 更改

[英]React, update and detect localStorage changes with a custom hook across different components

我有一個自定義掛鈎來管理localStorage ,如下所示:

import { useEffect, useState } from 'react'

export default function useLocalStorage(key, initValue) {

    const [state, setState] = useState(() => {
        const value = localStorage.getItem(key);
        if (value !== null) {
            return JSON.parse(value);
        }

        localStorage.setItem(key, JSON.stringify(initValue));
        return initValue;
    })

    useEffect(() => {
        localStorage.setItem(key, state);
    }, [key, state])
    
    return [state, setState];
}

此自定義掛鈎被聲明為在一個屏幕中為兩個或多個組件使用相同的本地存儲鍵。 例如。

const [state, setState] = useLocalStorage('key', false);

此時,由於使用useLocalStorage的組件要根據localStorage的狀態變化來工作,所以我們嘗試使用useEffect返回的狀態作為useLocalStorage的第二個參數。

useEffect(() => {
   foobar()
}, [state]);

我希望useEffect中的foobar()函數在聲明此useEffect的所有組件中的“狀態”發生變化時起作用。 但是, foobar()僅適用於使用相同useEffect的多個組件中的一個組件。為什么會發生這種情況? 我如何讓它按照我想要的方式工作?

您應該為存儲更改設置一個事件偵聽器,以便獲得更新的值。 請參閱下面的代碼和有關存儲事件的說明:

import { useEffect, useState } from 'react'

export default function useLocalStorage(key, initValue) {
  const [state, setState] = useState(() => {
    const value = localStorage.getItem(key);
    if (value !== null) {
      return JSON.parse(value);
    }

    localStorage.setItem(key, JSON.stringify(initValue));
    window.dispatchEvent(new Event("storage"));
    return initValue;
  });

  useEffect(() => {
    localStorage.setItem(key, state);
    window.dispatchEvent(new Event("storage"));
  }, [key, state]);

  useEffect(() => {
    const listenStorageChange = () => {
      setState(() => {
        const value = localStorage.getItem(key);
        if (value !== null) {
          return JSON.parse(value);
        }

        localStorage.setItem(key, JSON.stringify(initValue));
        window.dispatchEvent(new Event("storage"));
        return initValue;
      });
    };
    window.addEventListener("storage", listenStorageChange);
    return () => window.removeEventListener("storage", listenStorageChange);
  }, []);

  return [state, setState];
}

您可能想知道為什么要使用這個dispatchEvent 好吧,這就是 MDN 關於存儲事件的說法:

當存儲區域 ( localStorage ) 在another document的上下文中被修改時,會觸發Window接口的storage事件。

這個dispatchEvent是必需的,因為我們也需要監聽同一個文檔中的變化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM