0
0
Lập trình
NM

Cách Closures Định Hình Kiến Trúc Thành Phần Trong React

Đăng vào 1 tuần trước

• 4 phút đọc

Giới thiệu

Trong thế giới phát triển ứng dụng web, React đã trở thành một trong những thư viện phổ biến nhất để xây dựng giao diện người dùng. Nhiều nhà phát triển đã viết hàng trăm closures mà không nhận ra rằng chúng đã trở thành trung tâm của cách mà các thành phần (components) hoạt động trong React. Trong bài viết này, chúng ta sẽ khám phá cách closures đã chuyển đổi kiến trúc thành phần của React từ hướng đối tượng sang hướng hàm, cùng với những lợi ích và thách thức đi kèm.

Sự Chuyển Đổi Lớn: Từ Lớp Sang Closure

Ngày Xưa

Trước khi hooks ra đời, việc quản lý state trong các thành phần class khá phức tạp. Hãy xem một ví dụ:

javascript Copy
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
    this.increment = this.increment.bind(this); // Việc bind phức tạp
  }

  increment() {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return <button onClick={this.increment}>{this.state.count}</button>;
  }
}

Trong đoạn mã này, state sống trên các instance của thành phần. Các phương thức cần phải được bind. Điều này khiến cho mã trở nên khó đọc và bảo trì.

Sự Ra Đời Của Hooks

Khi hooks được giới thiệu, cách mà chúng ta viết thành phần đã thay đổi hoàn toàn:

javascript Copy
function Counter() {
  const [count, setCount] = useState(0);

  const increment = () => setCount(count + 1);

  return <button onClick={increment}>{count}</button>;
}

Điều này không chỉ làm cho mã sạch hơn mà còn thay đổi cách mà các thành phần hoạt động. Cấu trúc dựa trên closure cho phép chúng ta quản lý state, effects và event một cách hiệu quả hơn.

Kiến Trúc Thành Phần Dựa Trên Closure

Kiến trúc dựa trên closure trong React không chỉ là một cách viết khác, mà là một cách tư duy khác về cách mà các thành phần hoạt động. Đây là những điểm chính:

  • Giá trị state hiện tại được truy cập thông qua useState.
  • Props được truyền vào thành phần và có thể thay đổi.
  • Giá trị Context được truy cập thông qua useContext.
  • Bất kỳ biến nào từ scope bên ngoài cũng có thể được sử dụng.
javascript Copy
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const theme = useContext(ThemeContext);

  useEffect(() => {
    fetchUser(userId).then((user) => {
      setUser(user);
    });
  }, [userId]);

  const handleEdit = () => {
    editUser(user, theme);
  };

  return <div onClick={handleEdit}>{user?.name}</div>;
}

Mỗi lần render tạo ra các closures mới với các giá trị mới. Điều này cho phép React quản lý các state một cách linh hoạt và hiệu quả.

Thách Thức Quản Lý Bộ Nhớ

Kiến trúc dựa trên closure cũng mang đến những thách thức về bộ nhớ. Khi các thành phần unmount, việc dọn dẹp là rất quan trọng để tránh rò rỉ bộ nhớ. Các closures không chặn garbage collection trừ khi có một tham chiếu nào đó giữ chúng lại.

javascript Copy
function DataSubscription({ userId }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    const subscription = api.subscribe(userId, (newData) => {
      setData(newData);
    });

    return () => subscription.unsubscribe();
  }, [userId]);
}

Nếu không có cleanup, chúng ta có thể gặp phải tình trạng rò rỉ bộ nhớ nghiêm trọng.

Tối Ưu Hóa Qua Memoization

React cung cấp các hooks như useMemo và useCallback để quản lý vòng đời của closures một cách hiệu quả hơn:

javascript Copy
function ExpensiveComponent({ items, onSelect }) {
  const [filter, setFilter] = useState("");

  const filteredItems = useMemo(() =>
    items.filter((item) => item.name.includes(filter)),
    [items, filter]
  );

  const handleSelect = useCallback((id) => {
    onSelect(id);
  }, [onSelect]);

  return <ItemList items={filteredItems} onSelect={handleSelect} />;
}

Memoization giúp giảm thiểu việc tạo mới closures không cần thiết, từ đó cải thiện hiệu suất ứng dụng.

Kết Luận

Việc hiểu về kiến trúc thành phần dựa trên closure trong React không chỉ giúp bạn viết mã tốt hơn mà còn giúp bạn tư duy lại về cách xây dựng giao diện người dùng. Hãy thử áp dụng những kiến thức này vào dự án của bạn và chia sẻ kinh nghiệm trong phần bình luận dưới đây!

Câu Hỏi Thường Gặp

  1. Closure là gì?
    Closure là một hàm có quyền truy cập vào biến từ phạm vi của nó ngay cả khi hàm đó được gọi ở phạm vi khác.
  2. Tại sao useEffect lại tạo ra closure?
    useEffect tạo ra closure để ghi nhớ trạng thái tại thời điểm thực thi lần đầu, giúp quản lý hiệu ứng một cách chính xác.
  3. Làm thế nào để tránh rò rỉ bộ nhớ trong React?
    Luôn đảm bảo rằng bạn dọn dẹp các hiệu ứng và subscriptions khi các thành phần unmount.

Hãy tham gia vào cộng đồng và chia sẻ những gì bạn đã học được về closures trong React!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào