網站首頁 編程語言 正文
介紹
在這篇文章中,我會介紹 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
相關推薦
- 2022-09-20 linux?shell字符串截取的詳細總結(實用!)_linux shell
- 2022-03-28 Python獲取網絡時間戳的兩種方法詳解_python
- 2022-06-26 Android?app啟動節點與上報啟動實例詳解_Android
- 2022-08-01 Flask框架之數據交互的實現_python
- 2022-07-19 react Context的基本使用( react跨組件傳遞數據 )
- 2022-09-27 Hive中常用正則表達式的運用小結_正則表達式
- 2022-07-31 Python常見的幾種數據加密方式_python
- 2023-03-01 Golang中Append()使用實例詳解_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支