0

Bí mật đằng sau sức mạnh của Generator trong React

Bạn đang lạm dụng hook? Hãy sử dụng generator để tạo dữ liệu động trong component React, đơn giản hóa logic và giảm sự phụ thuộc vào hook. Hãy cùng tìm hiểu kỹ hơn ngay sau đây!

Generator là gì?

Generator là các hàm có thể tạm dừng và tiếp tục lại. Chúng được tạo bằng cách sử dụng khai báo function* và biểu thức yield.

function* generator() {
    yield 1;
    yield 2;
    yield 3;
}

const gen = generator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }

Bạn có thể sử dụng chúng để lặp qua một tập hợp dữ liệu hoặc để tạo một chuỗi dữ liệu. Chuỗi dữ liệu này sau đó có thể được sử dụng để render nội dung bên trong các component.

Vẫn còn bối rối? Hãy cùng xây dựng một ví dụ đơn giản để hiểu cách sử dụng generator.

Ví dụ về Tiêu đề

Giả sử bạn có một danh sách các tiêu đề mà bạn muốn render trong component của mình.

const headlines = [
    "Local Shops Thrive",
    "Team Wins Finals",
    "Stay Flu-Free",
    "New Phone Launch",
    "Sunny Week Ahead",
];

Bạn có thể làm điều đó bằng cách lặp qua mảng headlines và render từng tiêu đề bên trong component, thông qua việc lưu trữ chỉ mục dưới dạng một biến state.

import { useState } from "react";

const Headlines = () => {
    const [index, setIndex] = useState(0);

    return (
        <div>
            <h1>{headlines[index]}</h1>
            <button onClick={() => setIndex((index + 1) % headlines.length)}>
                Next
            </button>
        </div>
    );
};

Điều này hoạt động tốt cho đến khi bạn có một mảng tiêu đề tuyến tính mà bạn muốn lặp lại và hiển thị lặp đi lặp lại. Bây giờ, nếu bạn muốn tạo một mẫu với các tiêu đề của mình thì sao? Ví dụ: đầu tiên, hiển thị thông báo chào mừng dựa trên thời gian trong ngày, sau đó hiển thị ngày trong tuần và cuối cùng là một suy nghĩ tạo động lực ngẫu nhiên.

const headlines = [
    "Good Morning", // Greeting message
    "Today is Monday", // Day of the week
    "Stay positive", // Motivational thought
];

Bây giờ, bạn không thể chỉ đơn giản lặp lại một tập hợp dữ liệu tĩnh. Thay vào đó, bạn cần tính toán từng tiêu đề một cách linh hoạt.

Nhưng bạn là một người có đầu óc nhạy bén. Bạn nảy ra một ý tưởng: tại sao không tạo ba hàm tính toán từng phần của mẫu và sử dụng kết quả đầu ra của chúng làm văn bản render?

function getGreetingMessage() {
    const hours = new Date().getHours();
    if (hours < 12) {
        return "Good Morning";
    } else if (hours < 18) {
        return "Good Afternoon";
    } else {
        return "Good Evening";
    }
}

function getDayOfTheWeek() {
    const days = [
        "Sunday",
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday",
    ];
    return `Today is ${days[new Date().getDay()]}`;
}

function getMotivationalThought() {
    const thoughts = ["Stay positive", "Keep going", "You're awesome"];
    return thoughts[Math.floor(Math.random() * thoughts.length)];
}

Bây giờ, bạn có thể sử dụng các hàm này để render các tiêu đề bên trong component.

import { useState } from "react";

const Headlines = () => {
    const pattern = [
        getGreetingMessage,
        getDayOfTheWeek,
        getMotivationalThought,
    ];
    const [index, setIndex] = useState(0);

    return (
        <div>
            <h1>{pattern[index]()}</h1>
            <button onClick={() => setIndex((index + 1) % pattern.length)}>
                Next
            </button>
        </div>
    );
};

Bạn có nhận thấy điều gì không? Bạn đã thay đổi toàn bộ logic của component. Để đơn giản hóa logic và giữ cho component của bạn gọn gàng, bạn có thể sử dụng generator.

function* patternGenerator() {
    yield getGreetingMessage();
    yield getDayOfTheWeek();
    yield getMotivationalThought();
}

const pattern = patternGenerator();

Bây giờ, bạn có thể sử dụng generator này để render các tiêu đề bên trong component.

import { useState } from "react";

const Headlines = () => {
const [index, setIndex] = useState(0);

    return (
        <div>
            <h1>{pattern.next().value}</h1>
            <button onClick={() => setIndex((index + 1) % 3}>Next</button>
        </div>
    );

};

Bằng cách này, bạn có thể giữ cho component của mình gọn gàng và logic đơn giản. Generator có thể được sử dụng để đơn giản hóa logic và cho hook nghỉ ngơi. Generator cũng trừu tượng hóa logic đằng sau cách dữ liệu được tạo ra.

Thêm vào đó, bạn có thể dễ dàng mở rộng mẫu bằng cách thêm nhiều hàm vào generator hoặc thay đổi thứ tự của các hàm mà không làm thay đổi logic bên trong component. Để tiến thêm một bước nữa, bạn cũng có thể tạo một custom hook để xử lý logic generator.

import { useState } from "react";

function useGenerator(generator) {
    const [gen, setGen] = useState(generator());

    return () => gen.next().value;
}

const Headlines = () => {
    const pattern = useGenerator(patternGenerator);

    return (
        <div>
            <h1>{pattern()}</h1>
        </div>
    );
};

Điều này cũng đảm bảo rằng API cho generator vẫn nhất quán trên các component bất kể logic thay đổi như thế nào bên trong generator. Do đó, chúng cung cấp tính linh hoạt và kiểm soát nhiều hơn đối với quá trình tạo dữ liệu.

Lợi ích của việc sử dụng generator

  • Đơn giản hóa logic component với API nhất quán và tách biệt giữa việc tạo dữ liệu và render.
  • Cho phép tạo dữ liệu theo yêu cầu để giảm thiểu việc sử dụng state và tránh lưu trữ dữ liệu không cần thiết.
  • Cung cấp kiểm soát chi tiết và cách tiếp cận linh hoạt, có thể mở rộng để tạo dữ liệu.

Những điểm cần ghi nhớ

  • Generator không dành riêng cho React mà là một tính năng JavaScript thuần túy.
  • Chức năng tạm dừng và tiếp tục của generator giúp chúng tiết kiệm bộ nhớ.
  • Chúng không tạo ra các hiệu ứng phụ hoặc kích hoạt các cập nhật hoặc đột biến bất thường.

Kết luận

Generator giúp hợp lý hóa quy trình phân phối dữ liệu và tách biệt giữa việc tạo dữ liệu và render component, mang lại khả năng kiểm soát và tính linh hoạt cao hơn đối với việc tạo dữ liệu mà không ảnh hưởng đến hiệu suất.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.