[英]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
通过使用setFontSize
与setSize
匹配,则命名可能会更清晰。
({ 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.