[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog:post:vi:quan-ly-trang-thai-trong-react-redux-toolkit-va-react-query":3},{"slug":4,"lang":5,"title":6,"summary":7,"date":8,"tags":9,"tag_slugs":15,"thumbnail_url":16,"translations":17,"body":18,"asset_base":19},"quan-ly-trang-thai-trong-react-redux-toolkit-va-react-query","vi","Quản lý trạng thái trong React: Redux Toolkit và React Query","Khám phá cách kết hợp Redux Toolkit và React Query để quản lý trạng thái trong ứng dụng React một cách hiệu quả, đồng thời tối ưu hiệu suất và sự đơn giản trong lập trình.","2026-06-16",[10,11,12,13,14],"react","redux","state","query","typescript",[10,11,12,13,14],"https://blog-api.ro-proxy.com/api/blog/posts/quan-ly-trang-thai-trong-react-redux-toolkit-va-react-query/thumbnail.svg?lang=vi",[5],"\n## Giới thiệu\nTrong thế giới phát triển front-end hiện đại, việc quản lý trạng thái ứng dụng trở thành thách thức khi dự án phát triển tăng trưởng. Các thư viện như Redux Toolkit và React Query đã cho chúng ta những giải pháp mạnh mẽ nhưng thường được sử dụng riêng lẻ. Bài viết này sẽ hướng dẫn cách **kết hợp** hai công cụ này để tận dụng ưu điểm của từng thư viện: Redux Toolkit cho trạng thái đồng bộ, dữ liệu toàn cục và React Query cho fetch dữ liệu bất đồng bộ, caching, và refetch.\n\n## Redux Toolkit – Tóm tắt\nRedux Toolkit (RTK) được thiết kế để làm giảm boilerplate trong Redux. Một số tính năng nổi bật:\n\n- `createSlice` giúp tạo reducer và action trong một dòng.\n- `configureStore` tự động thiết lập thunk, devtools, và middleware.\n- `createAsyncThunk` hỗ trợ tạo async logic.\n\n### Ví dụ: Tạo slice người dùng\n```ts\nimport { createSlice, PayloadAction } from '@reduxjs/toolkit';\n\ninterface UserState {\n  id: string | null;\n  name: string;\n  loading: boolean;\n}\n\nconst initialState: UserState = {\n  id: null,\n  name: '',\n  loading: false,\n};\n\nconst userSlice = createSlice({\n  name: 'user',\n  initialState,\n  reducers: {\n    setName(state, action: PayloadAction\u003Cstring>) {\n      state.name = action.payload;\n    },\n  },\n  extraReducers: (builder) => {\n    builder\n      .addCase(fetchUser.pending, (state) => {\n        state.loading = true;\n      })\n      .addCase(fetchUser.fulfilled, (state, action) => {\n        state.id = action.payload.id;\n        state.name = action.payload.name;\n        state.loading = false;\n      })\n      .addCase(fetchUser.rejected, (state) => {\n        state.loading = false;\n      });\n  },\n});\n\nexport const { setName } = userSlice.actions;\nexport default userSlice.reducer;\n```\n\n## React Query – Tóm tắt\nReact Query (RQ) chuyên xử lý fetch dữ liệu, caching, optimistic updates, và refetch khi cần. Một số tính năng chính:\n\n- `useQuery` để fetch dữ liệu đơn giản.\n- `useMutation` cho các thao tác POST/PUT/DELETE.\n- Caching tự động, stale time, và refetch options.\n\n### Ví dụ: Fetch danh sách bài viết\n```ts\nimport { useQuery } from 'react-query';\n\nfunction usePosts() {\n  return useQuery('posts', async () => {\n    const res = await fetch('/api/posts');\n    return res.json();\n  });\n}\n\nexport default usePosts;\n```\n\n## Tích hợp Redux Toolkit và React Query\nMỗi thư viện phục vụ mục tiêu riêng: RTK cho state logic và phân phối toàn cục, RQ cho fetch, caching và sync dữ liệu từ server. Để **kết hợp** chúng, ta có thể:\n\n1. **Sử dụng RTK để lưu trữ dữ liệu đã fetch**: Khi RQ fetch dữ liệu thành công, dispatch một action lưu dữ liệu vào store.\n2. **Dùng RTK query**: RTK Query (phần mở rộng của RTK) có thể thay thế RQ trong một số trường hợp, nhưng nếu muốn **đồng bộ** giữa RTK Query và RQ, bạn có thể lắng nghe `onSuccess` của query.\n3. **Lọc tác động**: Đặt dữ liệu fetched từ RQ vào state của RTK để các component khác có thể subscribe mà không cần fetch lại.\n\n### Mã ví dụ: Ghi dữ liệu từ RQ vào RTK\n```ts\nimport { useDispatch } from 'react-redux';\nimport { useQuery } from 'react-query';\nimport { setPosts } from './store/postSlice';\n\nfunction Posts() {\n  const dispatch = useDispatch();\n  const { data, error, isLoading } = useQuery('posts', fetchPosts, {\n    onSuccess: (data) => {\n      dispatch(setPosts(data)); // lưu vào RTK\n    },\n  });\n\n  if (isLoading) return \u003Cp>Đang tải...\u003C/p>;\n  if (error) return \u003Cp>Lỗi: {error.message}\u003C/p>;\n\n  return (\n    \u003Cul>\n      {data.map((post) => (\n        \u003Cli key={post.id}>{post.title}\u003C/li>\n      ))}\n    \u003C/ul>\n  );\n}\n```\n\n## Mẹo và thực hành\n- **Chỉ lưu dữ liệu quan trọng** vào Redux. Nếu dữ liệu chỉ cần sử dụng trong component, giữ trong hook local.\n- **Sử dụng `select`**: Khi lấy dữ liệu từ RTK store, dùng `useSelector` với selector tốt để tránh re-render không cần thiết.\n- **Cấu trúc thư mục**: Tách riêng `store/` (Redux), `queries/` (React Query hooks), và `components/`.\n- **Error handling**: RQ cung cấp `onError`, RTK để quản lý lỗi đồng bộ.\n- **Testing**: Khi sử dụng RTK + RQ, test hook RQ bằng mock `react-query` provider, và test slice riêng.\n\n## Kết luận\nKết hợp Redux Toolkit với React Query giúp bạn tận dụng tối đa ưu điểm của hai công cụ: quản lý state đồng bộ, logic phức tạp và fetch dữ liệu hiệu quả, caching tốt, và đồng bộ dữ liệu một cách mượt mà. Đừng ngại thử nghiệm cách chia nhỏ dữ liệu giữa store và hook; một cấu hình hợp lý sẽ làm cho codebase dễ bảo trì và mở rộng.\n","https://blog-api.ro-proxy.com/api/blog/posts/quan-ly-trang-thai-trong-react-redux-toolkit-va-react-query/assets"]