使用 useState 和 useContext React Hooks 持久化 localStorage
Persistence with localStorage with useState and useContext React Hooks
我已经设置了一个 Provider 来为使用 useContext
的用户共享一些状态。因此,我试图利用本地存储为用户图像(头像等)保存一些状态
首先,我尝试为用户保留头像,本质上是从 express 中保存他们的 ID,然后在调用 Cloudinary(图像托管服务)时使用它。
我想我已经接近了(因为我得到了虚拟形象的默认图像占位符)但我无法设置本地存储。
import React, { useState, useEffect } from 'react';
import dynamic from 'next/dynamic';
var initialState = {
userId: null,
avatar: '/static/uploads/profile-avatars/placeholder.jpg'
};
var UserContext = React.createContext();
function getLocalStorage() {
return Object.keys(initialState).forEach(item => {
dynamic(
() =>
Object.keys(initialState).forEach(
val => (initialState[window.localStorage.getItem(item)] = val)
),
{
ssr: false
}
);
});
}
function setLocalStorage() {
Object.keys(initialState).forEach(item => {
console.log('item setLocalStorage', item);
dynamic(
() =>
window.localStorage.setItem(
item,
Object.values(initialState).forEach(item => item)
),
{
ssr: false
}
);
});
}
function UserProvider({ children }) {
var [userImages, setUserImages] = useState(() => getLocalStorage() || initialState);
var [userId, setUserId] = useState(userImages.userId);
useEffect(() => {
setLocalStorage();
}, [userId]);
return (
<UserContext.Provider
value={{
userImages,
setUserImages,
userId,
setUserId
}}
>
{children}
</UserContext.Provider>
);
}
export default UserContext;
export { UserProvider };
提前致谢,父亲节快乐!
我认为在这种情况下不需要 next/dynamic
。 ES2020 dynamic import()
用于动态导入 JavaScript 模块(包括 React 组件)。这里你没有导入任何东西。
此外,localStorage
中的键和值始终采用字符串格式。这就是为什么您可以跳过 null
值(否则它将被转换为字符串“null”)。我建议您使用 JSON.stringify
.
将整个用户状态存储为一个对象
所以 setLocalStorage()
和 getLocalStorage()
将是:
function setLocalStorage(key, value) {
try {
window.localStorage.setItem(key, JSON.stringify(value));
} catch (e) {
// catch possible errors:
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
}
}
function getLocalStorage(key, initialValue) {
try {
const value = window.localStorage.getItem(key);
return value ? JSON.parse(value) : initialValue;
} catch (e) {
// if error, return initial value
return initialValue;
}
}
然后,您可以在 UserProvider
中使用它们,如下所示:
function UserProvider({ children }) {
const [user, setUser] = useState(() => getLocalStorage("user", initialState));
useEffect(() => {
setLocalStorage("user", user);
}, [user]);
return (
<UserContext.Provider
value={{
userId: user.id,
userAvatar: user.avatar,
userImages: user.images,
setUserId: (id) => setUser({ ...user, id }),
setUserAvatar: (avatar) => setUser({ ...user, avatar }),
setUserImages: (images) => setUser({ ...user, images }),
}}
>
{children}
</UserContext.Provider>
);
}
我已经设置了一个 Provider 来为使用 useContext
的用户共享一些状态。因此,我试图利用本地存储为用户图像(头像等)保存一些状态
首先,我尝试为用户保留头像,本质上是从 express 中保存他们的 ID,然后在调用 Cloudinary(图像托管服务)时使用它。
我想我已经接近了(因为我得到了虚拟形象的默认图像占位符)但我无法设置本地存储。
import React, { useState, useEffect } from 'react';
import dynamic from 'next/dynamic';
var initialState = {
userId: null,
avatar: '/static/uploads/profile-avatars/placeholder.jpg'
};
var UserContext = React.createContext();
function getLocalStorage() {
return Object.keys(initialState).forEach(item => {
dynamic(
() =>
Object.keys(initialState).forEach(
val => (initialState[window.localStorage.getItem(item)] = val)
),
{
ssr: false
}
);
});
}
function setLocalStorage() {
Object.keys(initialState).forEach(item => {
console.log('item setLocalStorage', item);
dynamic(
() =>
window.localStorage.setItem(
item,
Object.values(initialState).forEach(item => item)
),
{
ssr: false
}
);
});
}
function UserProvider({ children }) {
var [userImages, setUserImages] = useState(() => getLocalStorage() || initialState);
var [userId, setUserId] = useState(userImages.userId);
useEffect(() => {
setLocalStorage();
}, [userId]);
return (
<UserContext.Provider
value={{
userImages,
setUserImages,
userId,
setUserId
}}
>
{children}
</UserContext.Provider>
);
}
export default UserContext;
export { UserProvider };
提前致谢,父亲节快乐!
我认为在这种情况下不需要 next/dynamic
。 ES2020 dynamic import()
用于动态导入 JavaScript 模块(包括 React 组件)。这里你没有导入任何东西。
此外,localStorage
中的键和值始终采用字符串格式。这就是为什么您可以跳过 null
值(否则它将被转换为字符串“null”)。我建议您使用 JSON.stringify
.
所以 setLocalStorage()
和 getLocalStorage()
将是:
function setLocalStorage(key, value) {
try {
window.localStorage.setItem(key, JSON.stringify(value));
} catch (e) {
// catch possible errors:
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
}
}
function getLocalStorage(key, initialValue) {
try {
const value = window.localStorage.getItem(key);
return value ? JSON.parse(value) : initialValue;
} catch (e) {
// if error, return initial value
return initialValue;
}
}
然后,您可以在 UserProvider
中使用它们,如下所示:
function UserProvider({ children }) {
const [user, setUser] = useState(() => getLocalStorage("user", initialState));
useEffect(() => {
setLocalStorage("user", user);
}, [user]);
return (
<UserContext.Provider
value={{
userId: user.id,
userAvatar: user.avatar,
userImages: user.images,
setUserId: (id) => setUser({ ...user, id }),
setUserAvatar: (avatar) => setUser({ ...user, avatar }),
setUserImages: (images) => setUser({ ...user, images }),
}}
>
{children}
</UserContext.Provider>
);
}