我正在尝试在next.js中创建一个能够适应页面刷新的useState
的替代品。
其中一个可能的解决方案是使用window.localStorage
来保存和检索状态,这样即使在页面刷新之后状态也会保持不变。
我发现了下面的ReactJS https://usehooks.com/useLocalStorage/的useLocalStorage
钩子实现
function useLocalStorage(key, initialValue) {
// State to store our value
// Pass initial state function to useState so logic is only executed once
const [storedValue, setStoredValue] = useState(() => {
if (typeof window === "undefined") {
return initialValue;
}
try {
// Get from local storage by key
const item = window.localStorage.getItem(key);
// Parse stored json or if none return initialValue
return item ? JSON.parse(item) : initialValue;
} catch (error) {
// If error also return initialValue
console.log(error);
return initialValue;
}
});
// Return a wrapped version of useState's setter function that ...
// ... persists the new value to localStorage.
const setValue = (value) => {
try {
// Allow value to be a function so we have same API as useState
const valueToStore =
value instanceof Function ? value(storedValue) : value;
// Save state
setStoredValue(valueToStore);
// Save to local storage
if (typeof window !== "undefined") {
window.localStorage.setItem(key, JSON.stringify(valueToStore));
}
} catch (error) {
// A more advanced implementation would handle the error case
console.log(error);
}
};
return [storedValue, setValue];
}
但是,当我在NextJS中使用它时,它生成了以下错误:
未捕获的错误:水合失败,因为初始UI与服务器上呈现的内容不匹配
经过一番搜索,我发现window
对象不存在于(Next.js)服务器端,这可能是错误(Window is not defined in Next.js React app)的原因。一个可能的解决方案是使用useEffect
钩子来保护window
的使用,该钩子只在客户端运行。
我当前的useLocalStorage
钩子实现是
function useLocalStorage<T>(key: string, defaultValue: T): [T, Dispatch<SetStateAction<T>>] {
const [value, setValue] = useState<T>(defaultValue);
useEffect(() => {
try {
const item = window.localStorage.getItem(key);
setValue(item ? JSON.parse(item) : defaultValue);
}
catch (error) {
setValue(defaultValue);
}
}, [key, defaultValue]);
useEffect(() => {
window.localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
};
然而,这一次钩子并不总是像预期的那样工作,因为useEffect回调的执行顺序没有得到保证,结果,有时状态会丢失。
我想知道在NextJS中什么是正确的实现,并了解我的代码逻辑在哪里失败。
3条答案
按热度按时间2w3rbyxf1#
下面是一个useLocalStorage钩子,它与next.js一起工作
jv4diomz2#
Markos的回答总是让我在刷新时重置状态,我添加了一个小调整,解决了这个问题:
ee7vknir3#
这对我很有效:Next.js use localstorage problem with SSR
......而且它不会像@MarkosTh09的解决方案那样在每次刷新时重置值。