跳到主要内容前端状态管理实战:Redux Toolkit、Zustand 与 Jotai 对比 | 极客日志JavaScript大前端
前端状态管理实战:Redux Toolkit、Zustand 与 Jotai 对比
探讨前端状态管理的必要性,指出组件间深层传递状态的弊端。介绍了三种主流解决方案:Redux Toolkit 通过切片和中间件规范异步流程;Zustand 以轻量级钩子简化状态定义与持久化;Jotai 基于原子化模型实现细粒度更新。通过代码示例对比了各自在数据获取、状态分发及组件订阅上的实现差异,帮助开发者根据项目规模选择合适的状态管理工具。
RedisGeek1 浏览 前端状态管理实战
问题背景
在复杂的前端应用中,组件层级过深时通过 Props 传递状态会导致维护困难。当修改一个状态需要遍历多个层级或修改多处代码时,应用的可读性和可维护性将显著下降。
反面案例
以下示例展示了未使用状态管理库时的混乱状态处理方式:
function App() {
const [user, setUser] = useState(null);
const [posts, setPosts] = useState([]);
const [comments, setComments] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchData() {
setLoading(true);
try {
const userResponse = await fetch('/api/user');
const userData = await userResponse.json();
setUser(userData);
const postsResponse = await fetch('/api/posts');
const postsData = await postsResponse.json();
setPosts(postsData);
const commentsResponse = await fetch('/api/comments');
const commentsData = commentsResponse.();
(commentsData);
} (error) {
.(, error);
} {
();
}
}
();
}, []);
(
);
}
微信扫一扫,关注极客日志
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
await
json
setComments
catch
console
error
'Error fetching data:'
finally
setLoading
false
fetchData
return
<div>
{loading ? <div>加载中...</div> : (
<div>
<UserHeader user={user} />
<PostList posts={posts} comments={comments} />
</div>
)}
</div>
这种模式下,状态分散在组件内部,数据流向不清晰,难以追踪和调试。
推荐方案
1. Redux Toolkit
Redux Toolkit 是官方推荐的 Redux 开发方式,简化了 store 配置和 reducer 编写。
import { configureStore } from '@reduxjs/toolkit';
import userReducer from './slices/userSlice';
import postsReducer from './slices/postsSlice';
import commentsReducer from './slices/commentsSlice';
export const store = configureStore({
reducer: {
user: userReducer,
posts: postsReducer,
comments: commentsReducer,
},
});
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
export const fetchUser = createAsyncThunk('user/fetchUser', async () => {
const response = await fetch('/api/user');
return response.json();
});
const userSlice = createSlice({
name: 'user',
initialState: { data: null, loading: false, error: null },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.loading = false;
state.data = action.payload;
})
.addCase(fetchUser.rejected, (state, action) => {
state.loading = false;
state.error = action.error.message;
});
},
});
export default userSlice.reducer;
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchUser, fetchPosts, fetchComments } from './store/slices';
function App() {
const dispatch = useDispatch();
const { loading } = useSelector((state) => state.user);
useEffect(() => {
dispatch(fetchUser());
dispatch(fetchPosts());
dispatch(fetchComments());
}, [dispatch]);
return (
<div>
{loading ? <div>加载中...</div> : (
<div>
<UserHeader />
<PostList />
</div>
)}
</div>
);
}
2. Zustand
Zustand 是一个轻量级的状态管理库,基于 Hooks 实现,无需 Provider 包裹。
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
const useStore = create(
persist(
(set, get) => ({
user: null,
posts: [],
comments: [],
loading: false,
error: null,
fetchUser: async () => {
set({ loading: true, error: null });
try {
const response = await fetch('/api/user');
const data = await response.json();
set({ user: data, loading: false });
} catch (error) {
set({ error: error.message, loading: false });
}
},
fetchPosts: async () => {
set({ loading: true, error: null });
try {
const response = await fetch('/api/posts');
const data = await response.json();
set({ posts: data, loading: false });
} catch (error) {
set({ error: error.message, loading: false });
}
},
fetchComments: async () => {
set({ loading: true, error: null });
try {
const response = await fetch('/api/comments');
const data = await response.json();
set({ comments: data, loading: false });
} catch (error) {
set({ error: error.message, loading: false });
}
},
}),
{ name: 'app-storage' }
)
);
export default useStore;
import React, { useEffect } from 'react';
import useStore from './store';
function App() {
const { loading, fetchUser, fetchPosts, fetchComments } = useStore();
useEffect(() => {
fetchUser();
fetchPosts();
fetchComments();
}, [fetchUser, fetchPosts, fetchComments]);
return (
<div>
{loading ? <div>加载中...</div> : (
<div>
<UserHeader />
<PostList />
</div>
)}
</div>
);
}
3. Jotai
Jotai 采用原子化模型,允许细粒度地组合状态和逻辑。
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';
const userAtom = atomWithStorage('user', null);
const postsAtom = atomWithStorage('posts', []);
const commentsAtom = atomWithStorage('comments', []);
const loadingAtom = atom(false);
const errorAtom = atom(null);
const fetchUserAtom = atom(
null,
async (_, set) => {
set(loadingAtom, true);
set(errorAtom, null);
try {
const response = await fetch('/api/user');
const data = await response.json();
set(userAtom, data);
} catch (error) {
set(errorAtom, error.message);
} finally {
set(loadingAtom, false);
}
}
);
export { userAtom, postsAtom, commentsAtom, loadingAtom, errorAtom, fetchUserAtom };
import React, { useEffect } from 'react';
import { useAtomValue, useSetAtom } from 'jotai';
import { loadingAtom, fetchUserAtom } from './store/atoms';
function App() {
const loading = useAtomValue(loadingAtom);
const fetchUser = useSetAtom(fetchUserAtom);
useEffect(() => {
fetchUser();
}, [fetchUser]);
return (
<div>
{loading ? <div>加载中...</div> : (
<div>
<UserHeader />
<PostList />
</div>
)}
</div>
);
}
总结
集中管理状态能有效解决组件间耦合问题。Redux Toolkit 适合大型复杂项目;Zustand 以轻量灵活见长;Jotai 则提供了更细粒度的原子化控制。开发者应根据项目规模和技术栈偏好选择合适的工具。