首页 > 解决方案 > 使用 useState 和 useContext React Hooks 持久化 localStorage

问题描述

我已经设置了一个 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 };

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

标签: reactjslocal-storagereact-hooksuse-stateuse-context

解决方案


我相信next/dynamic在这种情况下不需要。ES2020dynamic import()用于动态导入 JavaScript 模块(包括 React 组件)。在这里你没有导入任何东西。

此外,其中的键和值localStorage始终为字符串格式。这就是为什么你可以跳过null值(或者它会被转换为字符串“null”)。我建议您通过使用将整个用户状态存储为一个对象JSON.stringify

所以setLocalStorage()andgetLocalStorage()将是:

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>
  );
}

推荐阅读