繁体   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