使用 useState 和 useContext React Hooks 持久化 localStorage

Posted

技术标签:

【中文标题】使用 useState 和 useContext React Hooks 持久化 localStorage【英文标题】:Persistence with localStorage with useState and useContext React Hooks 【发布时间】:2020-10-11 17:31:25 【问题描述】:

我已经设置了一个 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)
        ),
      
        s-s-r: false
      
    );
  );


function setLocalStorage() 
  Object.keys(initialState).forEach(item => 
    console.log('item setLocalStorage', item);
    dynamic(
      () =>
        window.localStorage.setItem(
          item,
          Object.values(initialState).forEach(item => item)
        ),
      
        s-s-r: 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 ;

提前谢谢你,父亲节快乐!

【问题讨论】:

【参考方案1】:

我相信在这种情况下不需要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>
  );

【讨论】:

非常感谢!它真的帮助我更好地理解 localStorage! 我要特别感谢@Hangindev,因为这是一个非常棒且简单的解决方案,它让我的应用程序正常工作!!!!!!非常感谢!!!!

以上是关于使用 useState 和 useContext React Hooks 持久化 localStorage的主要内容,如果未能解决你的问题,请参考以下文章

ZF_react hooks useState的实现 useCallback useMemo useReducer useContext

useEffect 与 useContext 陷入无限循环

[包括useContext钩子使子代的useState重置为初始值

useContext 和 Redux 有啥区别? [关闭]

useContext 减少组件层级和useReducer的使用

useContext 减少组件层级和useReducer的使用