Next.js全局状态管理:zustand。以及cookie和seesion的实用剖析。

由于Next是基于React的,所以只要适用于react的库,Next几乎都可以使用。之前聊到关于官方给react推荐的全局状态管理库Redux。事实上它并不轻量便捷。在这方面我曾多次在社区请教这方面的大佬。得到的回复总结如下:Redux就是这样的,所以不到必要的时候我们推荐使用useContext。而redux我们推荐去处理那些复杂逻辑处理的全局状态。后来他们都推荐了一款更加轻量的库“zustand"。恰好,它甚至有针对Next.js的配置方案。官网地址:Zustand。由于它是英文的网址对我们这些英文文盲来说并不友好,当然也会有中文文档:ZUSTAND 中文文档 | ZUSTAND (awesomedevin.github.io)。但由于中文文档并非官方授权翻译的,可能有些解释会有晦涩难懂的情况。so,我们也需要加强对英文文档的理解或者翻译。

接下来我按照官网给的实例,结合自己的开发需求开始上手。(依照的是官方英文文档)

1. Zustand
Zustand 是一个轻量级的状态管理库,用于 JavaScript 应用程序,特别是在 React 生态系统中。它提供了一个简单、可扩展的解决方案来中心化和管理应用程序的状态。

与其他状态管理解决方案(如 Redux 或 MobX)相比,Zustand 旨在提供更简洁的 API 和更少的样板代码。它允许你创建一个全局状态存储,并且可以在应用程序的任何地方访问和更新这个状态,而不需要像 Redux 那样编写大量的 action creators 和 reducers。

Zustand 的主要特点包括:

简洁的 API:创建 store 和访问 state 都非常直观。
React hooks:Zustand 与 React hooks 完美整合,使得在 React 组件中使用状态变得非常简单。
不可变更新:通过 Immer 库支持,Zustand 允许你以一种直观的方式更新复杂的状态对象。
中间件支持:可以使用中间件来添加额外的功能,例如日志记录、持久化等。
没有“单一真相来源”的限制:与 Redux 不同,Zustand 允许你创建多个独立的 store。
Zustand 是在 React 社区内广受欢迎的解决方案之一,适用于那些想要更简单状态管理工具的开发者。

与 Redux 相比

从概念上讲,Zustand 和 Redux 非常相似,两者都基于不可变状态模型。但是,Redux 要求您的应用包装在上下文提供程序中;而 Zustand 则不需要。

(注意):由于zustand与redux相差不大,所以它们可以使用一种浏览器调试工具:"Redux DevTools",这个工具再chorm浏览器和edge浏览器插件商店都能获取到,所以就不分享了。

先来里描述下我的业务逻辑:用户登录后全会得到后端来的token值,和用户信息,目前token的唯一作用就是被携带进请求的请求头,所以我不考虑将它放入zustand而是放入cookie或者sisson。而用户的详细信息则需要,因为后面的一系列请求都要用到它的相关数据。可能会有小伙伴疑问:为什么不都一起放入cookie或者sisson呢?因为提供了一个选项:”记住我“,区别就是当用户关闭浏览器再次进入的时候会不会重新登录。当然如果间隔时间过长的话这取决与后端设置token的有效值和前端设置固定时间清除cookie的时间。好的!好像已经扯远了。接下来直接看代码。

import { createStore } from 'zustand/vanilla';
import { devtools } from 'zustand/middleware';

// 定义用户状态类型
export type UserState = {
  user: {} | null;
};

// 定义用户操作类型
export type UserActions = {
  setUser: (user: UserState['user']) => void;
  clearUser: () => void;
};

// 将状态和操作结合在一起形成完整的 Store 类型
export type UserStore = UserState & UserActions;

// 定义默认的初始状态
export const defaultInitState: UserState = {
  user: null,
};

// 创建用户存储的函数,接受一个可选的初始状态参数
export const userMessage = (initState: UserState = defaultInitState) => {
  // 创建 Zustand 存储并使用 devtools 进行调试
  return createStore<UserStore>()(
    devtools(set => ({
      ...initState,
      setUser: user => {
        console.log('Setting user:', user);
        set(() => ({ user }));
      },
      clearUser: () => {
        console.log('Clearing user');
        set(() => ({ user: null }));
      },
    }))
  );
};

我比较喜欢边写代码,便给出注释,所以不懂的看注释,我就不再复述。

我在页面里面是这样使用给它们的:

import { parseCookies } from 'nookies';
import { userMessage, UserState } from '@/stores/userStore';
......   .......

 // 获取 store 的实例
  const store = userMessage();
  useEffect(() => {
    // 从 sessionStorage 中获取 token 和用户信息
    const token = sessionStorage.getItem('token');
    const userMessage: any = sessionStorage.getItem('userMessage');
    console.log('userMessage', JSON.parse(userMessage));

    // 如果 sessionStorage 中没有找到,再从 cookie 中获取
    if (!token || !userMessage) {
      const cookies = parseCookies();
      const cookieToken = cookies.token;
      const cookieUserMessage = decodeURIComponent(cookies.userMessage); // 先进行 URL 解码
      console.log('cookieUserMessage', cookieUserMessage);
      if (cookieToken && cookieUserMessage) {
        store.getState().setUser(JSON.parse(cookieUserMessage));
      }
    } else {
      store.getState().setUser(JSON.parse(userMessage));
    }
    fetchData();
  }, [store]);

这里我用到一个不常用的api:”decodeURIComponent“,先说作用:存储在 cookie 中的值是经过 URL 编码的,这是一种将非 ASCII 字符转换为 ASCII 字符的方式,以确保数据在传输过程中不会出现问题。JSON.parse 无法直接解析这种 URL 编码后的字符串,因为它不是标准的 JSON 格式。

出现这个问题是因为后端返回给我的是一个json格式的对象,如果我将它不作处理就存入cookie它就是这样的”[object Object]“,所以我使用JSON.stringify把它转成了字符串类型,反正可以使用JSON.parse转回来。但是当我想从cookie转回来时它变成了”%7B%22userId%22%3A%229%22%2C%22username%22%3A%2218285873023%22%2C%22password%22%3A%22123456%22%2C%22phone%22%3A%2218285873023%22%7D“这样的ASCII 字符,JSON.parse处理后是null。

好的这就是我的分享。废话多了点,但也算是我的经验了吧,我的目的是记录一边后以后就不会再焦头烂额了。事实上从这片文章你学不到多少东西,我希望你去观摩官方文档,再来借鉴我的写法。其实使用方法不难,但仔细想想好像也没什么难得,一起加油吧!!

参考的文献:告别繁杂的状态管理:Zustand 的简洁之道_zustand useshallow-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值