日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

更強大的React?狀態管理庫Zustand使用詳解_React

作者:代碼與野獸 ? 更新時間: 2022-11-20 編程語言

介紹

在這篇文章中,我會介紹 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 部分就不展開了。

原文鏈接:https://juejin.cn/post/7150504990505697310

欄目分類
最近更新