簡體   English   中英

React Hooks 和 localStorage 沒有設置正確的值

[英]React Hooks and localStorage dont set correct value

你好,我有一個想法,做一個鈎子來增加字體大小並在 localStorage 中保存首選項基本上我有一個從 1 到 4 的狀態,然后當我單擊按鈕添加時,我將 +1 添加到狀態,直到我達到數字4 在刪除按鈕上,我從狀態中刪除 1 直到 1

但是,如果我不將 useState 僅與 getInitialValue 一起使用,我對如何將其保存到我的位置存有疑問,它可以正常工作。

像這個 gif,如果我手動添加值,它會起作用:

在此處輸入圖片說明

但是如果我嘗試使用我的 setFont 我有問題(因為它保存在 localStorage 中):

在此處輸入圖片說明

我在 localStorage 上得到了這個:

在此處輸入圖片說明

代碼:

export default function App() {
  const { fontSize, setSize } = useFontSize();
  console.log(fontSize);
  return (
    <div className="App">
      <button
        onClick={() => {
          setSize(fontSize + 1);
        }}
      >
        add
      </button>
      <button
        onClick={() => {
          setSize(fontSize + 1);
        }}
      >
        remove
      </button>
    </div>
  );
}

鈎:

export default function useFontSize(defaultSize = { size: 1 }) {
  const [fontSize, _setSize] = useState(getInitialSize);
  function getInitialSize() {
    const savedSize = localStorage.getItem('_size_acessibility_font');
    const parsedSize = JSON.parse(savedSize);
    if (parsedSize) {
      const { size } = parsedSize;
      if (size >= 1 && size <= 4) {
        return size;
      }
    } else {
      return defaultSize.size;
    }
  }

  useEffect(() => {
    console.log(fontSize, 'on useEffect to set on localStorage');
    localStorage.setItem(
      '_size_acessibility_font',
      JSON.stringify({ size: fontSize }),
    );
  }, [fontSize]);

  return {
    fontSize,
    setSize: ({ setSize, ...size }) => {
      console.log(size, 'on function set size');
      if (size > 4) {
        return _setSize(4);
      }
      if (size < 1) {
        return _setSize(1);
      }
      return _setSize(size);
    },
  };
}

例子:

https://codesandbox.io/s/focused-newton-x0mqd

如果有人可以幫助我,我不知道這是否是這種情況的最佳邏輯。

這似乎有點過度設計並擾亂了一些鈎子習語。 例如,為鈎子返回命名對象對不像數組對那么典型。 set函數本身很復雜,並返回_setSize調用的結果。 如果fontSize通過使用setFontSizesetSize匹配,則命名可能會更清晰。

({ setSize, ...size })是有問題的,因為調用者(正確地)提供了一個整數。

這是修復這些問題的最小完整版本(本地存儲被模擬,因為 Stack Snippets 是沙盒的):

 <script type="text/babel" defer> const localStorageMock = (() => { const storage = {}; return { getItem: k => storage[k], setItem: (k, v) => {storage[k] = v.toString();} }; })(); const {useState, useEffect} = React; const useFontSize = (defaultSize=1) => { const clamp = (n, lo=1, hi=4) => Math.min(hi, Math.max(n, lo)); const clean = n => isNaN(n) ? defaultSize : clamp(+n); const storageName = "_size_acessibility_font"; const fromStorage = clean(localStorageMock.getItem(storageName)); const [fontSize, setFontSize] = useState(fromStorage); useEffect(() => { localStorageMock.setItem(storageName, fontSize); }, [fontSize]); return [fontSize, size => setFontSize(clean(size))]; }; const App = () => { const [fontSize, setFontSize] = useFontSize(); return ( <div> <div>Font size: {fontSize}</div> <button onClick={() => setFontSize(fontSize + 1)}> + </button> <button onClick={() => setFontSize(fontSize - 1)}> - </button> </div> ); }; ReactDOM.render(<App />, document.body); </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

useFontSize ,您返回

return {
  fontSize,
  setSize: ({ setSize, ...size }) => {
    console.log(size, 'on function set size');
    if (size > 4) {
      return _setSize(4);
    }
    if (size < 1) {
      return _setSize(1);
    }
    return _setSize(size);
  },
};

然而,在App ,你可以調用setSize只是一個數量setSize(fontSize + 1); 當它期待一個對象時。

如果您更改useFontSize以返回

return {
  fontSize,
  setSize: (size) => {
    console.log(size, 'on function set size');
    if (size > 4) {
      return _setSize(4);
    }
    if (size < 1) {
      return _setSize(1);
    }
    return _setSize(size);
  },
};

它應該工作。

請注意,您需要清除當前的本地存儲,或添加一些錯誤檢查。

還要注意,雖然這只是一個例子,但 add 和 remove 都使用fontSize + 1

暫無
暫無

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

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