Thông tin liên hệ
- 036.686.3943
- admin@nguoicodonvn2008.info
Khi quản lý trạng thái phức tạp trong app Next, mọi thứ có thể trở nên khó khăn. Tuy nhiên, bạn có thể khắc phục bằng cách tìm hiểu nguyên tắc cơ bản của React và quản lý trạng thái qua ứng dụng kinh điển này.

Trước khi bắt đầu làm app liệt kê việc cần làm, bạn phải chuẩn bị:
Trạng thái ứng dụng chỉ điều kiện của app hiện tại ở một thời điểm nhất định, bao gồm thông tin & quản lý app, như input người dùng và tìm nạp dữ liệu từ database hoặc một API (Application Programming Interface).
Để hiểu trạng thái ứng dụng, hãy cân nhắc các trường hợp có thể của một app bộ đếm đơn giản, bao gồm:
Một thành phần React có thể đăng ký thay đổi trạng thái. Khi người dùng tương tác với một thành phần như thế, những tác vụ như click nút bấm có thể update trạng thái này.
Đoạn code dưới hiện một ứng dụng bộ đếm đơn giản, ở trạng thái mặc định, được dùng để quản lý trạng thái các tác vụ click:
const [counter, setCounter] = useState(0);
return (
<main>
<h1>{counter}</h1>
<button onClick={() => setCounter(counter + 1)}>increase</button>
<button onClick={() => setCounter(counter - 1)}>decrease</button>
<button onClick={() => setCounter(0)}>reset</button>
</main>
);
Repository của dự án chứa hai nhánh: starter và context. Bạn có thể dùng nhánh khởi đầu làm cơ sở để xây dựng dự án từ đầu hoặc nhánh ngữ cảnh để xem trước bản demo cuối cùng.
App khởi đầu cung cấp UI bạn cần cho ứng dụng cuối cùng, vì thế, bạn có thể tập trung vào triển khai logic cốt lõi. Mở terminal và chạy lệnh sau để nhân bản nhánh starter của repository vào máy cục bộ:
git clone -b starter https://github.com/makeuseofcode/Next.js-CRUD-todo-app.git
Chạy lệnh sau, trong thư mục dự án để cài đặt các phần phụ thuộc và khởi chạy server phát triển:
yarn && yarn dev
Hoặc:
npm i && npm run dev
Nếu tất cả đều chạy tốt, UI sẽ hiện trong trình duyệt của bạn:

Context API cung cấp một cách để quản lý và chia sẻ dữ liệu trạng thái trên các thành phần mà không cần prop drilling theo cách thủ công.
Tạo thư mục src/app/context để lưu file ngữ cảnh và giữ thư mục dự án được tổ chức tốt. Trong thư mục này, tạo file todo.context.jsx chứa tất cả logic ngữ cảnh cho ứng dụng này.
Nhập hàm createContext từ thư viện react và gọi nó, lưu trữ kết quả trong một biến:
import { createContext} from "react";
const TodoContext = createContext();
Tiếp theo, tạo một hook useTodoContext trả về TodoContext dưới dạng biểu mẫu khả dụng.
export const useTodoContext = () => useContext(TodoContext);
Để thực hiện CRUD (tạo, đọc, update, xóa) của ứng dụng, bạn cần tạo trạng thái và quản lý chúng với thành phần Provider.
const TodoContextProvider = ({ children }) => {
const [task, setTask] = useState("");
const [tasks, setTasks] = useState([]);
return <TodoContext.Provider value={{}}>{children}</TodoContext.Provider>;
};
export default TodoContextProvider;
Ngay trước lệnh return, tạo hàm handleTodoInput chạy khi các kiểu người dùng nằm trong to-do. Hàm này sau đó update trạng thái task.
const handleTodoInput = (input) => setTask(input);
Thêm hàm createTask chạy khi người dùng gửi một app to-do. Hàm này update trạng thái tasks và gắn ID ngẫu nhiên cho nhiệm vụ mới.
const createTask = (e) => {
e.preventDefault();
setTasks([
{
id: Math.trunc(Math.random() * 1000 + 1),
task,
},
...tasks,
]);
};
Tạo hàm updateTask ánh xạ qua danh sách tasks và update nhiệm vụ chứa ID khớp với ID của nhiệm vụ được click.
const updateTask = (id, updateText) =>
setTasks(tasks.map((t) => (t.id === id ? { ...t, task: updateText } : t)));
Tạo hàm deleteTask update danh sách tasks để nó bao gồm tất cả nhiệm vụ chứa ID không khớp với tham số được cung cấp.
const deleteTask = (id) => setTasks(tasks.filter((t) => t.id !== id));
Giờ bạn đã tạo trạng thái và viết code để quản lý chúng, bạn cần làm những hàm trạng thái và xử lý có sẵn cho Provider. Bạn có thể cung cấp chúng dưới dạng một đối tượng, dùng thuộc tính value của thành phần Provider.
return (
<TodoContext.Provider
value={{
task,
tasks,
handleTodoInput,
createTask,
updateTask,
deleteTask,
}}
>
{children}
</TodoContext.Provider>
);
Provider đã tạo phải chứa thành phần top-level để tạo ngữ cảnh sẵn có cho toàn bộ ứng dụng. Để làm việc này, chỉnh sửa src/app/page.jsx và bao gồm thành phần Todos với TodoContextProvider:
<TodoContextProvider>
<Todos />;
</TodoContextProvider>;
Chỉnh sửa file src/app/components/Todos.jsx và hủy cấu trúc tasks, task, handleTodoInput, và createTask qua cuộc gọi tới hàm useTodoContext.
const { task, tasks, handleTodoInput, createTask } = useTodoContext();
Giờ, update thành phần biểu mẫu để xử lý sự kiện gửi và đổi sang trường đầu vào chính:
<form onSubmit={(e) => createTask(e)}>
<input className="todo-input" type="text" placeholder="Enter a task" required value={task} onChange={(e) => handleTodoInput(e.target.value)} />
<input className="submit-todo" type="submit" value="Add task" />
</form>
Giờ bạn có thể dùng ứng dụng để tạo và thêm một nhiệm vụ vào list tasks. Để update hiển thị, bạn cần ánh xạ qua tasks hiện có và hiện chúng trong UI. Đầu tiên, tạo src/app/components/Todo.jsx chứa một mục cần làm.
Trong src/app/components/Todo.jsx, chỉnh sửa hoặc xóa một nhiệm vụ bằng cách gọi các hàm updateTask và deleteTask đã tạo trong tệp src/app/context/todo.context.jsx.
import React, { useState } from "react";
import { useTodoContext } from "../context/todo.context";
const Todo = ({ task }) => {
const { updateTask, deleteTask } = useTodoContext();
// isEdit state tracks when a task is in edit mode
const [isEdit, setIsEdit] = useState(false);
return (
<table className="todo-wrapper">
<tbody>
<tr>
{isEdit ? ( <input type="text" value={task.task}
onChange={(e) => updateTask(task.id, e.target.value)} /> ) :
(<th className="task">{task.task}</th> )}
<td className="actions">
<button className="edit"
onClick={() => setIsEdit(!isEdit)}> {isEdit ? "Save" : "Edit"} </button>
<button onClick={() => deleteTask(task.id)}>Del</button>
</td>
</tr>
</tbody>
</table>
);
};
export default Todo;
Để hiện src/app/components/Todo.jsx cho từng task, đi sâu vào file src/app/components/Todos.jsx và ánh xạ có điều kiện qua tasks ngay sau khi đóng thẻ header.
{tasks && (
<main>
{tasks.map((task, i) => ( <Todo key={i} task={task} /> ))}
</main>
)}
Kiểm tra ứng dụng trong trình duyệt và xác nhận nó cho kết quả mong đợi.

Hi vọng bài viết hữu ích với các bạn.
Nguồn tin: Quantrimang.com
Ý kiến bạn đọc
Những tin mới hơn
Những tin cũ hơn
Cách cấu hình agent để giao tiếp bằng nhiều ngôn ngữ trong ElevenAgents
Hướng dẫn dùng Claude Haiku 5.5 làm trợ lý phân loại trong Claude Code
Cách thiết kế giọng nói sống động, lôi cuốn cho ElevenLabs Agents
Cách kết nối Google Drive với Gemini Spark đọc và xử lý tài liệu
Chế độ Sinh viên trong Gemini: Không gian học tập có lộ trình
Cách biến ý tưởng thành thiết kế bằng MagicPath trong ChatGPT
TOP công cụ AI tạo workflow tốt nhất
TOP trình duyệt web AI tốt nhất
Cách cung cấp kiến thức phù hợp cho agent trong Microsoft Copilot Studio
Thiết lập cơ sở kiến thức cho ElevenAgents
15 prompt AI thú vị cho ngày lễ Halloween
Hướng dẫn chat bằng giọng nói trên Dola AI
Top công cụ AI tốt nhất cho Digital Marketing
Hướng dẫn tạo giọng nói cá nhân trên Dola AI
tOP plugin ChatGPT tốt nhất để lên kế hoạch du lịch
Trình tự đảm bảo tính an toàn cho quy trình tự động hóa trong Grok Bot
Tìm hiểu về chế độ Expressive trong ElevenAgents
Cách kích hoạt plugin Gmail trên ChatGPT và prompt ví dụ
TOP plugin Notion hữu ích nên sử dụng ngay
Hướng dẫn tạo video chúc mừng ngày Nhà giáo Việt Nam 20/11
Cách lập trình chuyên nghiệp hơn, dễ dàng hơn với tính năng Tệp trên Grok
Hướng dẫn cài đặt và sử dụng n8n trên Windows 11
Công thức tính diện tích hình Elip
Hướng dẫn ngắt kết nối ứng dụng trên ChatGPT
Hướng dẫn tạo đoạn hội thoại cho topic trên Twee
6 cách mở Computer/System Properties trong Windows 10
Đừng chia sẻ ảnh cho đến khi bạn chạy kiểm tra siêu dữ liệu này!
Bức tranh tổng quan về hỗ trợ khách hàng tích hợp AI
Cách sửa lỗi There Are Currently No Power Options Available Windows
Hướng dẫn 8 cách mở bàn phím ảo trên Windows 10