ReactJS được tạo ra bởi Facebook vào năm 2013, đã thay đổi hoàn toàn cách các developer xây dựng giao diện người dùng. Nhưng ít ai biết rằng cái tên React bắt nguồn từ chính mục đích ban đầu Facebook tạo ra nó: làm cho các ứng dụng có thể "phản hồi" nhanh chóng với thay đổi dữ liệu.
Vậy điều gì làm ReactJS trở nên phổ biến và tại sao mọi người lại yêu thích nó đến vậy, hãy cùng mình khám phá trong bài viết này.
1. ReactJS là gì?
Thực tế thì tên chính thức của thư viện là React, không phải ReactJS, điều này được xác nhận từ trang web chính thức reactjs.org. Thuật ngữ ReactJS được sử dụng không chính thức trong cộng đồng lập trình viên như một cách để phân biệt với React Native (phiên bản phát triển cho mobile). Vì thế mình xin phép sử dụng tên gọi ReactJS và React thay thế cho nhau xuyên suốt bài viết này nhé.
React (ReactJS) là một thư viện JavaScript mã nguồn mở, được dùng để xây dựng giao diện người dùng (frontend) cho web. React chỉ tập trung vào phần hiển thị giao diện (view), chứ không can thiệp vào cách sắp xếp logic nghiệp vụ hoặc cấu trúc ứng dụng.
Điều này mang lại cho lập trình viên nhiều tự do hơn khi thiết kế frontend so với các framework khác. Tuy nhiên, sự tự do này cũng làm cho React khó học hơn với người mới bắt đầu, đặc biệt khi phải quản lý các ứng dụng lớn.
2. Những đặc điểm nổi bật của React
Các bạn biết đấy, luôn luôn tồn tại cuộc tranh luận về việc framework nào là tốt nhất để phát triển giao diện web. Các framework lớn như Angular, Vue, và thư viện React là những lựa chọn phổ biến trên thị trường, nhưng không có ai là "người thắng cuộc" tuyệt đối, mà chỉ có giải pháp nào phù hợp hơn với nhu cầu của bạn.
2.1 Linh hoạt trong Thiết kế kiến trúc
React tập trung vào việc hiển thị giao diện người dùng và cho phép lập trình viên tự do quyết định cách sắp xếp logic nghiệp vụ. Chính sự linh hoạt này làm cho React trở nên phổ biến, vì nó phù hợp với nhiều loại dự án và phong cách phát triển khác nhau.
Khác với các framework có kiến trúc cố định như Angular, React không ép buộc người dùng vào một mô hình cụ thể, khiến nó linh hoạt cho nhiều dự án khác nhau. Mặc dù điều này trong React đem lại lợi ích cho lập trình viên có kinh nghiệm, nhưng lại gây khó khăn cho người mới bắt đầu vì thiếu sự hướng dẫn cụ thể.
Ví dụ: Với ứng dụng TODO list, React chỉ giúp bạn hiển thị danh sách các công việc (tasks
) ra màn hình. Bạn phải tự tạo các hàm addTask
và deleteTask
để thêm và xóa công việc. Các logic nghiệp vụ (xử lý thêm/xóa) hoàn toàn do bạn quyết định, không bị ép buộc theo bất kỳ quy tắc nào.
import React, { useState } from 'react';
function TodoApp() {
// Dùng useState để quản lý danh sách công việc
const [tasks, setTasks] = useState([]);
// Hàm thêm công việc mới
const addTask = (task) => {
setTasks([...tasks, task]); // Thêm vào danh sách
};
// Hàm xóa công việc theo chỉ số (index)
const deleteTask = (index) => {
const newTasks = tasks.filter((_, i) => i !== index); // Xóa công việc
setTasks(newTasks);
};
return (
<div>
<h1>Danh sách công việc</h1>
<ul>
{tasks.map((task, index) => (
<li key={index}>
{task} <button onClick={() => deleteTask(index)}>Xóa</button>
</li>
))}
</ul>
<button onClick={() => addTask("Công việc mới")}>Thêm công việc</button>
</div>
);
}
export default TodoApp;
Trong khi đó Angular bắt buộc bạn phải tách biệt logic thêm/xóa công việc vào service (TodoService
) và component chỉ để hiển thị danh sách công việc. Bạn không thể viết mọi thứ trong cùng một nơi như React, Angular quy định rõ ràng cách thức tổ chức ứng dụng.
Ngược lại, một framework như Angular sẽ giống như có bản thiết kế nhà sẵn, và bạn phải xây nhà theo đúng bản thiết kế đó. Nếu bạn muốn thay đổi điều gì, bạn cần tuân thủ những quy tắc có sẵn, chẳng hạn như cách bố trí phòng, vị trí cửa sổ, hay các hệ thống điện và nước.
2.2 Kiến trúc Component đơn giản và nhẹ
React được xây dựng dựa trên kiến trúc component, nơi mỗi thành phần có thể được tái sử dụng, giúp ứng dụng dễ mở rộng và duy trì. Các component trong React rất nhẹ và có thể chỉ là các hàm đơn giản trả về JSX.
Điều này giúp các lập trình viên dễ dàng phát triển các ứng dụng lớn hơn bằng cách chia nhỏ thành các thành phần độc lập, có thể tái sử dụng mà không cần phải lo về việc tích hợp phức tạp.
2.3 Cộng đồng hỗ trợ lớn
Một trong những lý do chính khiến React trở nên phổ biến là nhờ vào số lượng người dùng lớn và sự hỗ trợ từ cộng đồng cũng như các công cụ học tập. Đây là yếu tố quan trọng giúp các lập trình viên, đặc biệt là người mới bắt đầu, dễ dàng học và sử dụng React một cách hiệu quả.
Các diễn đàn lớn như Stack Overflow, Reddit, Dev.to, và Github chứa đầy các câu hỏi, câu trả lời và bài viết liên quan đến React, giúp người học dễ dàng tìm thấy sự trợ giúp khi gặp khó khăn.
React được duy trì và phát triển bởi Facebook (Meta), một trong những công ty công nghệ lớn nhất thế giới. Điều này đảm bảo rằng React sẽ nhận được sự hỗ trợ liên tục và các bản cập nhật mới, giúp lập trình viên yên tâm rằng React sẽ tiếp tục phát triển và phù hợp với các dự án dài hạn.
3. Các thành phần quan trọng trong ReactJS
3.1 JSX
JSX (JavaScript XML) là một cú pháp mở rộng cho phép bạn viết mã giống như HTML trong JavaScript. Trong các ngôn ngữ khác, bạn thường phải viết code HTML và JavaScript riêng rẽ. Tuy nhiên, với JSX, React cho phép bạn kết hợp cả hai trong cùng một mã nguồn, giúp quản lý dễ dàng hơn, đặc biệt là trong các ứng dụng phức tạp.
function TodoList() {
const tasks = ['Học React', 'Luyện tập JSX', 'Xây dựng ứng dụng'];
return (
<div>
<h1>Danh sách công việc</h1>
<ul>
{tasks.map((task, index) => (
<li key={index}>{task}</li>
))}
</ul>
</div>
);
}
3.2 Virtual DOM
Virtual DOM (Document Object Model ảo) là một bản sao nhẹ hơn của DOM thật. DOM thật là cấu trúc cây chứa tất cả các thành phần HTML trong trang web. Khi người dùng tương tác với ứng dụng (ví dụ: nhập văn bản, nhấn nút), ứng dụng sẽ thay đổi nội dung và DOM thật phải được cập nhật.
Tuy nhiên, việc cập nhật trực tiếp DOM thật có thể gây ra tình trạng chậm chạp và kém hiệu quả, đặc biệt trong các ứng dụng lớn với nhiều phần tử. Để giải quyết vấn đề này, React sử dụng Virtual DOM, với mục đích chỉ những phần có sự thay đổi mới được cập nhật lên DOM thật, giúp tiết kiệm thời gian và tài nguyên.
Giả sử bạn đang có một danh sách công việc (To-Do List), khi bạn thêm một công việc mới vào danh sách, React sẽ không cập nhật lại toàn bộ danh sách. Thay vào đó, nó chỉ cập nhật phần tử mới được thêm vào.
import React, { useState } from 'react';
function TodoList() {
const [tasks, setTasks] = useState(['Công việc 1', 'Công việc 2']);
const addTask = () => {
setTasks([...tasks, `Công việc mới`]);
};
return (
<div>
<ul>
{tasks.map((task, index) => (
<li key={index}>{task}</li>
))}
</ul>
<button onClick={addTask}>Thêm công việc</button>
</div>
);
}
export default TodoList;
3.3 Kiến trúc dựa trên Component
Component là các đơn vị cơ bản trong React, cung cấp cấu trúc cho giao diện người dùng. Mỗi component được khuyến khích càng nhỏ gọn và độc lập càng tốt để có thể tái sử dụng trong nhiều phần của ứng dụng hoặc thậm chí trong các ứng dụng khác.
Ví dụ bạn đang phát triển một ứng dụng quản lý danh sách công việc (To-Do List). Ứng dụng này có thể được chia thành các component như sau:
- App: Component chính, quản lý trạng thái của danh sách công việc thông qua useState và truyền dữ liệu xuống các component con (TodoList, AddTodo).
- TodoList: Component nhận danh sách công việc từ App thông qua props và hiển thị mỗi công việc bằng cách gọi TodoItem.
- TodoItem: Component hiển thị chi tiết từng công việc trong danh sách.
- AddTodo: Component quản lý biểu mẫu để thêm công việc mới. Nó nhận một hàm onAdd từ App để thêm công việc mới vào danh sách.
import React, { useState } from 'react';
// Component chính: App
function App() {
const [todos, setTodos] = useState([]);
// Hàm thêm công việc mới
const addTodo = (newTodo) => {
setTodos([...todos, newTodo]);
};
return (
<div>
<h1>Danh sách công việc</h1>
<AddTodo onAdd={addTodo} />
<TodoList todos={todos} />
</div>
);
}
// Component TodoList: Hiển thị danh sách các công việc
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo, index) => (
<TodoItem key={index} todo={todo} />
))}
</ul>
);
}
// Component TodoItem: Hiển thị một công việc trong danh sách
function TodoItem({ todo }) {
return <li>{todo}</li>;
}
// Component AddTodo: Biểu mẫu thêm công việc mới
function AddTodo({ onAdd }) {
const [inputValue, setInputValue] = useState('');
// Hàm xử lý khi bấm nút thêm
const handleAdd = () => {
if (inputValue.trim()) {
onAdd(inputValue);
setInputValue(''); // Xóa nội dung sau khi thêm
}
};
return (
<div>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Nhập công việc mới"
/>
<button onClick={handleAdd}>Thêm</button>
</div>
);
}
export default App;
Các component như TodoItem hoặc AddTodo có thể được tái sử dụng trong nhiều phần khác nhau của ứng dụng hoặc trong các dự án khác mà không cần viết lại code. Component độc lập và tập trung vào một chức năng cụ thể giúp việc bảo trì hoặc thay đổi code trở nên dễ dàng hơn.
3.4 Liên kết dữ liệu một chiều
Trong React, dữ liệu được quản lý và luân chuyển theo hướng từ component cha xuống component con. Các component cha có thể truyền dữ liệu cho component con thông qua props, nhưng các component con không thể trực tiếp thay đổi dữ liệu của component cha.
Nếu muốn thay đổi dữ liệu, component con sẽ kích hoạt một hành động hoặc sự kiện (như nhấn nút), và component cha sẽ là nơi xử lý thay đổi dữ liệu đó. Giả sử chúng ta có một ứng dụng đơn giản với một button và số đếm. Mỗi khi người dùng nhấn button, số đếm sẽ tăng lên.
// Tạo component con để hiển thị số đếm
function DisplayCounter({ count }) {
return <h1>Số đếm: {count}</h1>;
}
// Tạo component cha để quản lý state và điều khiển tăng số đếm
import React, { useState } from 'react';
import DisplayCounter from './DisplayCounter'; // Import component con
function CounterApp() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1); // Cập nhật state mỗi khi nhấn nút
};
return (
<div>
<DisplayCounter count={count} />
<button onClick={increment}>Tăng số đếm</button>
</div>
);
}
export default CounterApp;
Component CounterApp
quản lý statecount
. Mỗi khi người dùng nhấn nút "Tăng số đếm", hàm increment
sẽ được gọi và statecount
được cập nhật. Giá trị mới của count
được truyền xuống DisplayCounter qua props và hiển thị số mới trên giao diện. Dữ liệu chỉ đi một chiều, từ CounterApp
(component cha) xuống DisplayCounter
(component con) qua props.
4. Kết luận
ReactJS là một thư viện JavaScript mạnh mẽ và linh hoạt, được thiết kế để giúp việc xây dựng giao diện người dùng trở nên đơn giản và hiệu quả hơn. Mặc dù có một số thách thức ban đầu với mô hình luồng dữ liệu một chiều (One-Way Data Binding), nhưng một khi nắm vững, React mang lại nhiều lợi ích vượt trội khi phát triển ứng dụng với quy mô lớn.
Các bài viết liên quan tại Blog 200Lab:
Bài viết liên quan
React Toastify là gì? Hướng dẫn sử dụng Toast Notification với React Toastify
Nov 21, 2024 • 7 min read
Hướng dẫn sử dụng Zustand trong NextJS
Nov 21, 2024 • 8 min read
Lazy Loading: Kỹ thuật Tối ưu Hiệu suất Website
Nov 17, 2024 • 14 min read
Hướng dẫn sử dụng Redux Toolkit và Redux Saga trong dự án React
Nov 15, 2024 • 10 min read
WebGL là gì? Hướng dẫn tạo đồ họa đơn giản với WebGL
Nov 13, 2024 • 7 min read
Test-Driven Development (TDD) là gì? Hướng dẫn thực hành TDD
Nov 13, 2024 • 6 min read