[英]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.