更强大的React 状态管理库Zustand使用详解

 更新时间:2022年10月08日 09:41:30   作者:代码与野兽  
这篇文章主要为大家介绍了更强大的React 状态管理库Zustand使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

介绍

在这篇文章中,我会介绍 Zustand 在实际项目中的使用。

我会构建一个 GitHub 用户搜索项目,在项目中通过调用 GitHub API 来实现搜索用户的功能。我还会并演示如何直接从 Zustand 存储中进行 API 调用,并将状态持久化到 sessionStorage 或 localStorage 中。

完成效果如下:

创建项目项目

首先,我们需要创建一个新的 React 应用程序。

我们需要在终端中运行命令来下面的命令来创建项目:

npx create-react-app github-user-search --template typescript

这行命令会利用 CRA 创建一个常规的 typescript react 项目。

安装项目依赖

创建项目后,我们需要进入该项目文件夹中。

cd github-user-search

并在终端中运行以下命令来安装项目所需要的依赖项:

npm i zustand @chakra-ui/react @emotion/react @emotion/styled react-icons react-router-dom axios framer-motion pluralize query-string react-helmet-async react-hook-form react-paginate 
  • zustand:状态管理库。
  • @chakra-ui/react:UI 库。
  • @emotion/react:CSS-in-JS 库。
  • @emotion/styled:CSS-in-JS 库。
  • react-icons:图标库。
  • react-router-dom:路由库。
  • axios:HTTP 请求库。
  • framer-motion:动画库。
  • pluralize:单词处理库。
  • query-string:URL 查询字符串库。
  • react-helmet-async:React 异步线程安全库。
  • react-hook-form:React 表单库。
  • react-paginate:React 分页库。

创建项目结构

安装好项目依赖后,我们需要创建项目所需要的目录结构。

项目目录结构如下:

src
├── index.tsx
├── assets
├── container
├── components
├── pages
├── routes
├── services
├── store
└── theme

设置环境变量

创建项目结构后,我们需要创建环境变量。

在项目根目录中创建一个 .env 文件,并在其中添加以下变量:

REACT_APP_GITHUB_API_URL=https://api.github.com

服务

创建环境变量后,我们需要创建服务。

在项目的 services 文件夹中创建一个 githubService.ts 文件,并添加以下代码:

import axios from 'axios';
import qs from 'query-string';
const github = axios.create({
    baseURL: process.env.REACT_APP_GITHUB_API_URL,
});
interface IGet {
    url: string;
    query?: Record<string, any>;
}
const get = async <T>({ url, query = {} }: IGet): Promise<T> => {
    const queryString = `?${qs.stringify(query)}`;
    const response = await github.get(`${url + queryString}`);
    return response.data;
};
const methods = { get };
export default methods;

设置 store

接下来,我们将建立我们的 Github store。我们将实现 Zutsand persist 方法来将我们的状态持久化到 sessionStorage 或 localStorage 中。

在 stores/github.ts 中添加代码:

import create from 'zustand';
import { stringify } from 'query-string';
import { persist } from 'zustand/middleware';
import methods from 'services/github';
import { IUserDetails, ISearchResonse, IGithubStore } from 'stores/types';
export const githubStore = create(
  persist<IGithubStore>(
    (set, get) => ({
      isLoading: false,
      cached_users_details: [], // to cache users details
      query: { page: 1, per_page: 20 },
      search: async (query) => {
        try {
          set(() => ({ isLoading: true }));
          window.history.pushState('', '', `?${stringify(query)}`);
          const data = await methods.get<ISearchResonse>({
            url: '/search/users',
            query,
          });
          set(() => ({ data, query, isLoading: false }));
        } catch (err: any) {
          const error =
            err?.message || err?.data?.message || 'Unexpected network error.';
          set(() => ({ isLoading: false, error }));
        }
      },
      getUser: async (username) => {
        try {
          set(() => ({ isLoading: true }));
          // check if user is already cached
          const userDetails = get().cached_users_details.find(
            (u) => u.login === username
          );
          if (userDetails) {
            set(() => ({ userDetails, isLoading: false }));
          } else {
            const userInfo = await methods.get<IUserDetails>({
              url: `/users/${username}`,
            });
            set((state) => ({
              cached_users_details: [...state.cached_users_details, userInfo],
              userDetails: userInfo,
              isLoading: false,
            }));
          }
        } catch (err: any) {
          const error =
            err?.message || err?.data?.message || 'Unexpected network error.';
          set(() => ({ isLoading: false, error }));
        }
      },
    }),
    {
      name: 'search-storage',
      getStorage: () => sessionStorage,
    }
  )
);

我们能够对 GitHub api 进行异步调用,并直接从我们的 store 很好地处理响应,而无需使用额外的中间件。

我们还缓存了我们的用户详细信息,这样我们就不必再次调用 API 来再次获取相同的用户详细信息。我们还将我们的状态持久化到会话存储中。

我们还可以通过将 getStorage 方法的返回值更改为 localStorage,来将我们的状态持久化到 localStorage 中。

清除/重置存储

目前,Zustand 没有关于清除/重置存储开箱即用的方法。

我们可以通过向我们的 store 添加一个 clear/reset 方法,将我们的状态重置回初始状态并调用 sessionStorage 或 localStorage clear() 方法保持数据的同步。

const initialState = {
  data: undefined,
  userDetails: undefined,
  cached_users_details: [],
  query: { page: 1, per_page: 20 },
  isLoading: false,
  error: undefined,
};
export const githubStore = create(
  persist<IGithubStore>(
    (set, get) => ({
      ...initialState,
      ...
      clear: () => {
        set(() => (initialState));
        sessionStorage.clear(); // or localStorage.clear();
      },
   })
  )
);

本文主要关注的是 Zustand 状态管理部分,UI 部分就不展开了。

以上就是更强大的React 状态管理库Zustand使用详解的详细内容,更多关于React 状态管理库Zustand的资料请关注脚本之家其它相关文章!

相关文章

  • React中使用Echarts无法显示title、tooltip等组件的解决方案

    React中使用Echarts无法显示title、tooltip等组件的解决方案

    这篇文章主要介绍了React中使用Echarts无法显示title、tooltip等组件的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • 详解React中的useMemo和useCallback的区别

    详解React中的useMemo和useCallback的区别

    React中的useMemo和useCallback是两个重要的Hooks。常常被用于优化组件的性能。虽然这两个Hooks看起来很相似,但它们彼此之间还是有很大的区别的,随着小编一起来学习吧
    2023-04-04
  • React 18版本配置rem 和 vw的详细步骤

    React 18版本配置rem 和 vw的详细步骤

    这篇文章主要介绍了React 18版本配置rem 和 vw的详细步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-01-01
  • React+Electron快速创建并打包成桌面应用的实例代码

    React+Electron快速创建并打包成桌面应用的实例代码

    这篇文章主要介绍了React+Electron快速创建并打包成桌面应用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12
  • 在React项目中使用TypeScript详情

    在React项目中使用TypeScript详情

    这篇文章主要介绍了在React项目中使用TypeScript详情,文章通过围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • react实现点击选中的li高亮的示例代码

    react实现点击选中的li高亮的示例代码

    本篇文章主要介绍了react实现选中的li高亮的示例代码,页面上有很多个li,要实现点击到哪个就哪个高亮。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • React 18中的state概念与使用、注意问题解决

    React 18中的state概念与使用、注意问题解决

    state和props类似,都是一种存储属性的方式,但是不同点在于state只属于当前组件,其他组件无法访问,这篇文章主要介绍了React 18中的state概念与使用、注意问题,需要的朋友可以参考下
    2022-12-12
  • React.js入门实例教程之创建hello world 的5种方式

    React.js入门实例教程之创建hello world 的5种方式

    React 是近期非常热门的一个前端开发框架。应用非常广泛,接下来通过本文给大家介绍React.js入门实例教程之创建hello world 的5种方式 ,需要的朋友参考下吧
    2016-05-05
  • React 错误边界Error Boundary使用示例解析

    React 错误边界Error Boundary使用示例解析

    这篇文章主要为大家介绍了React 错误边界Error Boundary使用示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • antd 3.x Table组件如何快速实现虚拟列表详析

    antd 3.x Table组件如何快速实现虚拟列表详析

    这篇文章主要给大家介绍了关于antd 3.x Table组件如何快速实现虚拟列表的相关资料,文中通过实例代码介绍的非常详细,对大家学习或者使用antd具有一定的参考学习价值,需要的朋友可以参考下
    2022-11-11

最新评论