Xây dựng ứng dụng CRUD với Redux Toolkit cực dễ dàng
Trong bài viết này, tôi sẽ hướng dẫn bạn cách sử dụng Redux Toolkit để quản lý trạng thái của ứng dụng React. Chúng ta sẽ tập trung vào cách xây dựng cấu trúc thư mục chuẩn cho Redux Toolkit và tầm quan trọng của việc này. Bên cạnh đó, tôi sẽ cung cấp một số mã ví dụ để minh họa cách thực hiện.
Nếu bạn đang tìm kiếm cách sử dụng Redux Toolkit trong dự án của mình một cách hiệu quả và dễ dàng bảo trì, bài viết này sẽ cung cấp cho bạn những thông tin hữu ích.
Tại sao nên sử dụng Bộ công cụ Redux?
- Dễ dàng thiết lập store: Redux Toolkit cung cấp các công cụ giúp thiết lập store một cách nhanh chóng và dễ dàng hơn. Bạn không cần phải viết lại các boilerplate code khi sử dụng Redux Toolkit.
- Hỗ trợ các thư viện phổ biến: Redux Toolkit tích hợp sẵn các thư viện phổ biến như Immer js, Redux, Redux Thunk, Reselect, Redux DevTools Extension, giúp cho việc xây dựng ứng dụng với Redux trở nên thuận tiện và hiệu quả hơn.
- Giảm thiểu boilerplate code: Redux Toolkit cung cấp các công cụ giúp giảm thiểu boilerplate code, giúp bạn tập trung vào việc phát triển tính năng của ứng dụng mà không phải mất nhiều thời gian viết code trùng lặp.
- Hỗ trợ Redux DevTools Extension: Redux Toolkit tích hợp Redux DevTools Extension, giúp bạn dễ dàng debug ứng dụng Redux của mình.
I. Cấu trúc thư mục chuẩn của Redux Toolkit
Redux Toolkit là một thư viện giúp đơn giản hóa việc sử dụng Redux trong ứng dụng React. Khi xây dựng ứng dụng sử dụng Redux Toolkit, việc sắp xếp thư mục và các file cần được quan tâm để giữ cho mã nguồn dễ đọc, dễ bảo trì và dễ mở rộng.
Dưới đây là cấu trúc thư mục chuẩn được đề xuất bởi Redux Toolkit:
Bài viết này được đăng tại [free tuts .net]
src/ ├── app/ │ ├── App.js │ ├── store.js │ └── rootReducer.js ├── features/ │ ├── feature1/ │ │ ├── feature1Slice.js │ │ ├── feature1API.js │ │ ├── feature1Page.js │ │ ├── feature1Form.js │ │ └── feature1List.js │ ├── feature2/ │ │ ├── feature2Slice.js │ │ ├── feature2API.js │ │ ├── feature2Page.js │ │ ├── feature2Form.js │ │ └── feature2List.js │ └── ... ├── components/ │ ├── Header.js │ ├── Footer.js │ └── ... ├── styles/ │ ├── theme.js │ ├── globalStyles.js │ └── ... └── index.js // https://freetuts.net
Các thư mục và tệp tin trong cấu trúc thư mục chuẩn của Redux Toolkit có các vai trò và mục đích như sau:
-`app/`: Thư mục này chứa tệp tin liên quan đến việc khởi tạo store Redux, root reducer và component chính của ứng dụng (App.js).
+`App.js`: Component chính của ứng dụng.
+`store.js`: Tệp tin khởi tạo Redux store.
+`rootReducer.js`: Tệp tin chứa root reducer của ứng dụng.
-`features/`: Thư mục này chứa các tính năng (features) của ứng dụng. Mỗi tính năng có thể bao gồm các tệp tin sau:
+`featureSlice.js`: Tệp tin chứa slice của tính năng đó.
+`featureAPI.js`: Tệp tin chứa các hàm API để giao tiếp với backend (nếu có).
+`featurePage.js`: Component chứa UI để hiển thị tính năng.
+`featureForm.js`: Component chứa form để thêm mới hoặc cập nhật dữ liệu của tính năng.
+`featureList.js`: Component chứa danh sách dữ liệu của tính năng.
-`components/`: Thư mục này chứa các components được sử dụng chung trong ứng dụng.
-`styles/`: Thư mục này chứa các tệp tin liên quan đến CSS của ứng dụng, bao gồm cả tệp tin CSS chung cho toàn bộ ứng dụng và các tệp tin CSS riêng cho từng component.
-`components/`: Thư mục này chứa các component của ứng dụng, mỗi component được đặt trong một thư mục riêng. Mỗi thư mục component bao gồm ít nhất hai tệp tin là:
+`index.js`: được sử dụng để export component tương ứng.
+`componentName.js`: chứa mã nguồn của componen
II. Thiết lập Create-React-App Với Redux
Create-React-App là một công cụ tạo ứng dụng React nhanh chóng và dễ dàng, tuy nhiên, nó không bao gồm Redux. Trong bài viết này, chúng ta sẽ tìm hiểu cách cài đặt Redux cho một ứng dụng Create-React-App.
Tạo ứng dụng Create-React-App
Để bắt đầu, hãy tạo một ứng dụng Create-React-App bằng cách chạy lệnh sau trong terminal:
npx create-react-app my-ap
Chúng ta sẽ sử dụng tên "my-app" trong ví dụ này, bạn có thể đổi tên nếu muốn.
Sau khi quá trình cài đặt hoàn tất, hãy mở thư mục của ứng dụng bằng lệnh sau:
cd my-ap
Cài đặt Redux và React-Redux
Tiếp theo, chúng ta cần cài đặt Redux và React-Redux bằng lệnh sau:
npm install --save redux react-redu
Tạo store
Chúng ta sẽ tạo file store.js trong thư mục src để định nghĩa Redux store. File này sẽ export ra store object.
import { createStore } from 'redux'; import rootReducer from './reducers'; const store = createStore(rootReducer); // https://freetuts.net export default store;
Trong đó, createStore là hàm để tạo store của Redux, rootReducer là reducer chính của ứng dụng.
Sử dụng useSelector() hook của React Redux
Để lấy dữ liệu từ store và sử dụng useDispatch()
hook để dispatch các action tương ứng.
Ví dụ:
import React from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { addUser, deleteUser, updateUser } from './usersSlice'; function UserList() { const users = useSelector(state => state.users); const dispatch = useDispatch(); const handleAddUser = () => { const newUser = { id: 1, name: 'John Doe' }; dispatch(addUser(newUser)); }; const handleDeleteUser = id => { dispatch(deleteUser(id)); }; const handleUpdateUser = (id, updatedUser) => { dispatch(updateUser({ id, ...updatedUser })); }; return ( <div> <button onClick={handleAddUser}>Add User</button> {users.map(user => ( <div key={user.id}> <span>{user.name}</span> <button onClick={() => handleDeleteUser(user.id)}>Delete</button> <button onClick={() => handleUpdateUser(user.id, { name: 'New Name' })}>Update</button> </div> ))} </div> ); } export default UserList;
Đó là những bước cơ bản để xây dựng một ứng dụng CRUD với Redux Toolkit. Bạn có thể tham khảo thêm tài liệu và ví dụ tại trang chủ của Redux Toolkit để biết thêm chi tiết.
Tạo reducer
Chúng ta sẽ tạo reducer chính của ứng dụng trong file src/reducers/index.js. Trong ví dụ này, chúng ta sẽ tạo một reducer đơn giản để lưu trữ giá trị số lần nhấn nút.
const initialState = { count: 0, }; function rootReducer(state = initialState, action) { switch (action.type) { case 'INCREMENT': return { ...state, count: state.count + 1 }; case 'DECREMENT': return { ...state, count: state.count - 1 }; default: return state; } } // https://freetuts.net export default rootReducer;
Kết nối store với ứng dụng
Trong file src/index.js, chúng ta sẽ import store và wrap ứng dụng bằng provider để cung cấp store cho toàn bộ ứng dụng.
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import store from './store'; import App from './App'; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') // https://freetuts.net );
Sử dụng store trong ứng dụng React
Sau khi đã khởi tạo store, bạn có thể sử dụng nó trong ứng dụng React bằng cách sử dụng Provider component của Redux. Provider component sẽ giúp các component con trong ứng dụng có thể truy cập đến store.
Trong file index.js, import Provider và wrap App component bằng Provider component:
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import App from './App'; import store from './store'; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') // https://freetuts.net // );
Sau đó, trong các component con của App, bạn có thể truy cập đến store bằng cách sử dụng hooks useSelector và useDispatch của Redux.
Ví dụ, trong component Counter, để truy cập đến state của counter trong store, bạn có thể sử dụng useSelector như sau:
import { useSelector } from 'react-redux'; function Counter() { const counter = useSelector(state => state.counter); return ( <div> <h1>Counter: {counter}</h1> </div> ); // https://freetuts.net // }
Để dispatch một action đến store, bạn có thể sử dụng useDispatch như sau:
import { useDispatch } from 'react-redux'; import { increment, decrement } from './counterSlice'; function Counter() { const counter = useSelector(state => state.counter); const dispatch = useDispatch(); return ( <div> <h1>Counter: {counter}</h1> <button onClick={() => dispatch(increment())}>+</button> <button onClick={() => dispatch(decrement())}>-</button> </div> ); // https://freetuts.net // }
Trong đoạn code trên, khi người dùng click vào button + hoặc - thì một action tương ứng sẽ được dispatch đến store. Các component khác trong ứng dụng cũng có thể truy cập đến store và dispatch action tương tự như vậy.
Đó là cách sử dụng store của Redux trong ứng dụng React đã được tạo bằng Create React App.
III. Tạo Slice Reducer và Actions cho Redux Toolkit
Redux Toolkit cung cấp một cách tiếp cận mới cho việc tạo reducer và actions, được gọi là "Slice". Slice là một khái niệm quan trọng trong Redux Toolkit và cung cấp một cách để định nghĩa reducer và actions của một phần của state. Trong phần này, chúng ta sẽ tạo một slice để quản lý một danh sách các task.
Tạo file Slice
Tạo một file mới trong thư mục "features" và đặt tên là taskSlice.js. File này sẽ chứa reducer và actions của slice.
Sau đó, chúng ta cần import createSlice từ Redux Toolkit:
import { createSlice } from '@reduxjs/toolkit';
Khởi tạo Slice
Tiếp theo, chúng ta sẽ sử dụng createSlice để khởi tạo slice:
const taskSlice = createSlice({ name: 'tasks', initialState: [], reducers: { addTask: (state, action) => { const newTask = { id: Date.now(), text: action.payload, completed: false }; state.push(newTask); }, toggleTask: (state, action) => { const task = state.find(task => task.id === action.payload); if (task) { task.completed = !task.completed; } }, deleteTask: (state, action) => { const index = state.findIndex(task => task.id === action.payload); if (index !== -1) { state.splice(index, 1); } } } // https://freetuts.net // });
Ở đây, chúng ta định nghĩa một slice có tên "tasks" và khởi tạo state ban đầu là một mảng rỗng. Sau đó, chúng ta định nghĩa các reducers cho slice bằng cách sử dụng cú pháp:
reducerName: (state, action) => { // update state here // https://freetuts.net // }
Ví dụ, reducer "addTask" sẽ thêm một task mới vào state bằng cách tạo một task mới với nội dung được truyền vào từ action payload và đưa nó vào mảng state.
Export reducer và actions
Cuối cùng, chúng ta sẽ xuất ra reducer và các actions của slice:
export const { addTask, toggleTask, deleteTask } = taskSlice.actions; export default taskSlice.reducer; // https://freetuts.net //
Như vậy, chúng ta đã tạo ra một slice với reducer và các actions tương ứng cho việc quản lý một danh sách các task. Bằng cách sử dụng Slice, chúng ta đã giảm thiểu được việc viết boilerplate code và tăng tính sáng tạo cho việc quản lý state trong Redux Toolkit.
Kết Luận
Tóm tắt lại, việc xây dựng cấu trúc thư mục chuẩn cho dự án sử dụng Redux Toolkit là rất quan trọng để giúp mã nguồn dễ đọc và bảo trì. Bằng cách tuân theo các quy ước và hướng dẫn đơn giản, bạn có thể tổ chức dự án của mình một cách rõ ràng và hiệu quả.
Dưới đây là các tài liệu tham khảo hữu ích dành cho bạn:
1. Tài liệu Bộ công cụ Redux: https://redux-toolkit.js.org/
2. Hướng dẫn phong cách Redux:http://https://redux.js.org/style-guide/style-guide/
3. Mô hình tổ chức Redux: https://github.com/erikras/ducks-modular-redux
`