React 19: Hook Mới Cho Nhà Phát Triển

7 min read

Trong phiên bản React 19, chúng ta không chỉ được chứng kiến những cải tiến về hiệu suất và tích hợp Web, mà còn có một loạt các hook mới hấp dẫn. Các hook này giúp bạn quản lý trạng thái, xử lý hiệu ứng và tương tác với API một cách dễ dàng hơn bao giờ hết. Hãy cùng khám phá những hook mới trong React 19 và tận hưởng trải nghiệm phát triển động

Các Hook mới

1.use()

Trong phiên bản React 19 sẽ giới thiệu một hook mới gọi là use(). Đây là hook giúp chúng ta có thể đơn giản hoá việc sử dụng promises, async code, và context.

Dưới đây là cách sử dụng hook để thực hiện việc gọi api:

const fetchUsers = async () => {
    const res = await fetch('https://jsonplaceholder.typicode.com/users');
    return res.json();
  };
  
  const UsersItems = () => {
    const users = use(fetchUsers());
  
    return (
      <ul>
        {users.map((user) => (
          <div key={user.id}>
            <h2 className='text-xl font-bold'>{user.name}</h2>
            <p>{user.email}</p>
          </div>
        ))}
      </ul>
    );
  }; 
export default UsersItems;

Ngoài ra bạn còn có thể sử dụng hook mới này với Context. API Context là một cách phổ biến để quản lý trạng thái toàn cục trong React mà không cần sử dụng bất kỳ thư viện quản lý trạng thái nào. Với hook use, hook context sẽ trông như mã sau:

import { createContext, useState, use } from 'react';

const ThemeContext = createContext();

const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

const Card = () => {
  // use Hook()
  const { theme, toggleTheme } = use(ThemeContext);

  return (
    <div
      className={`p-4 rounded-md ${
        theme === 'light' ? 'bg-white' : 'bg-gray-800'
      }`}
    >
      <h1
        className={`my-4 text-xl ${
          theme === 'light' ? 'text-gray-800' : 'text-white'
        }`}
      >
        Theme Card
      </h1>
      <p className={theme === 'light' ? 'text-gray-800' : 'text-white'}>
       Hello!! use() hook
      </p>
      <button
        onClick={toggleTheme}
        className='bg-blue-500 hover:bg-blue-600 text-white rounded-md'
      >
        {theme === 'light' ? 'Switch Dark Mode' : 'Switch Light Mode'}
      </button>
    </div>
  );
};

const Theme = () => {
  return (
    <ThemeProvider>
      <Card />
    </ThemeProvider>
  );
};

export default Theme

2.useFormStatus()

Hook mới này trong React 19 này sẽ giúp bạn có nhiều kiểm soát hơn đối với các biểu mẫu bạn tạo ra. Nó sẽ cung cấp thông tin trạng thái về việc nộp biểu mẫu cuối cùng.

const { pending, data, method, action } = useFormStatus();
  • Pending: Một giá trị boolean. Nếu true, điều này có nghĩa là biểu mẫu cha <form> đang chờ xử lý gửi. Nếu không, false.
  • Data: Một đối tượng thực hiện FormData interface chứa dữ liệu mà biểu mẫu cha <form> đang gửi. Nếu không có hoạt động gửi nào hoặc không có biểu mẫu cha <form>, nó sẽ là null.
  • Method: Một giá trị chuỗi là ‘get’ hoặc ‘post’. Điều này thể hiện rằng biểu mẫu cha <form> đang gửi với phương thức HTTP GET hoặc POST. Mặc định, một <form> sẽ sử dụng phương thức GET và có thể được chỉ định bởi thuộc tính method.
  • Action: Một tham chiếu đến hàm được truyền cho thuộc tính action trên biểu mẫu cha <form>. Nếu không có biểu mẫu cha <form>, thuộc tính này là null. Nếu có một giá trị URI được cung cấp cho thuộc tính action, hoặc không có thuộc tính action được chỉ định, action sẽ là null.

Dưới đây là ví dụ:

import { useFormStatus } from "react-dom";
import action from './actions';

function Submit() {
  const status = useFormStatus();
  return <button disabled={status.pending}>Submit</button>
}

export default function App() {
  return (
    <form action={action}>
      <Submit />
    </form>
  );
}

3.useActionState()

useActionState() là hook cho phép bạn cập nhật trạng thái dựa trên kết quả form action.

const [state, formAction] = useActionState(fn, initialState, permalink?);

Parameters

  • fn: Là hàm sẽ được gọi khi form được submit hoặc nhấn button.
  • initialState: Đây là giá trị ban đầu, nó có thể là bất kì giá trị tuần tự nào và đối số này sẽ được bỏ qua sau khi hành động được gọi lần đầu tiên.
  • permalink(optional): Là một URL hoặc liên kết trang, nếu fn được chạy trên server thì trang sẽ được chuyển hướng đến permalink.

Returns

  • state: Là trạng thái hiện tại. Trong lần đầu tiên render thì nó sẽ là initialState. Sau khi action được gọi thì nó sẽ là giá trị được trả về bởi action đó.
  • formAction: một hành động sẽ được truyền cho thuộc tính action của biểu mẫu. Giá trị trả về của hành động này sẽ có sẵn trong trạng thái.

Dưới đây là ví dụ về cách sử dụng hook:

import { useFormState} from 'react-dom';

const FormState = () => {
    const submitForm = (prevState, queryData) => {
        const name =  queryData.get("username");
        console.log(prevState); // previous form state
        if(name === 'john'){
            return {
                success: true,
                text: "Welcome"
            }
        }
        else{
            return {
                success: false,
                text: "Error"
            }
        }
    }
    const [ message, formAction ] = useFormState(submitForm, null)
    return <form action={formAction}>
        <label>Name</label>
        <input type="text" name="username" />
        <button>Submit</button>
        {message && <h1>{message.text}</h1>}
    </form>
}

export default FormState;

4.useOptimistic()

useOptimistic() là một hook trong React cho phép bạn hiển thị một trạng thái khác trong khi một hành động không đồng bộ đang diễn ra. Hook này rất hữu ích cho các ứng dụng cần tương tác với máy chủ, giúp cải thiện trải nghiệm người dùng bằng cách hiển thị kết quả dự kiến ngay lập tức.

Dưới đây là cú pháp của useOptimistic hook:

const [optimisticState, addOptimistic] = useOptimistic(
    state,
    // updateFn
    (currentState, optimisticValue) => {
      // merge and return new state
      // with optimistic value
    }
  );

Parameters

  • state: Giá trị sẽ được trả về ban đầu và bất cứ khi nào không có hành động nào đang chờ xử lý.
  • updateFn: Một hàm nhận vào trạng thái hiện tại và giá trị tối ưu được truyền vào addOptimistic, và trả về trạng thái tối ưu kết quả. Nó phải là một hàm thuần túy. updateFn nhận hai tham số: currentStateoptimisticValue. Giá trị trả về sẽ là giá trị kết hợp của currentStateoptimisticValue.

Returns

  • optimisticState: Trạng thái tối ưu kết quả. Nó bằng với state trừ khi có một hành động đang chờ xử lý, trong trường hợp đó nó bằng với giá trị trả về bởi updateFn.
  • addOptimistic: addOptimistic là hàm dispatch được gọi khi bạn có một cập nhật tối ưu. Nó nhận một đối số, optimisticValue, thuộc bất kỳ loại nào và sẽ gọi updateFn với stateoptimisticValue.

Ví dụ dưới đây minh họa cách triển khai useOptimistic để hiển thị trạng thái tối ưu khi người dùng gửi một form:

import { useOptimistic, useState } from "react";

const OptimisticComponent = () => {
  const [messages, setMessages] = useState([
    { text: "Hey, I am initial!", sending: false, key: 1 },
  ]);

  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) => [
      ...state,
      {
        text: newMessage,
        sending: true,
      },
    ]
  );

  async function sendFormData(formData) {
    const sentMessage = await fakeDelayAction(formData.get("message"));
    setMessages((messages) => [...messages, { text: sentMessage }]);
  }

  async function fakeDelayAction(message) {
    await new Promise((res) => setTimeout(res, 1000));
    return message;
  }

  const submitData = async (userData) => {
    addOptimisticMessage(userData.get("username"));
    await sendFormData(userData);
  };

  return (
    <>
      {optimisticMessages.map((message, index) => (
        <div key={index}>
          {message.text}
          {!!message.sending && <small> (Sending...)</small>}
        </div>
      ))}
      <form action={submitData}>
        <h1>OptimisticState Hook</h1>
        <div>
          <label>Username</label>
          <input type="text" name="username" />
        </div>
        <button type="submit">Submit</button>
      </form>
    </>
  );
};

export default OptimisticComponent;

Giải thích:

  • messages: chứa trạng thái ban đầu của các tin nhắn.
  • optimisticMessages: chứa trạng thái tối ưu, được cập nhật ngay lập tức khi người dùng gửi form.
  • fakeDelayAction: mô phỏng độ trễ của hành động gửi dữ liệu.
  • submitData: thêm tin nhắn vào trạng thái tối ưu và gửi dữ liệu form.

Khi người dùng gửi form, trạng thái tối ưu sẽ hiển thị ngay lập tức dưới dạng tin nhắn “Sending…”. Sau khi nhận được phản hồi từ máy chủ, tin nhắn này sẽ được cập nhật với nội dung thực tế.

useOptimistic giúp cải thiện trải nghiệm người dùng bằng cách cung cấp phản hồi ngay lập tức trong khi chờ đợi kết quả thực tế từ máy chủ.

Kết Luận

React 19 mang đến nhiều cải tiến và sự thay đổi đáng kể trong cách chúng ta sử dụng các hook. Đặc biệt, sự ra đời của hook mới use giúp quản lý promise, mã bất đồng bộ, và context trở nên dễ dàng hơn bao giờ hết.

Ngoài ra, các hook mới như useFormStatus, useFormState, và useOptimistic giúp chúng ta quản lý trạng thái form và phản hồi người dùng một cách hiệu quả hơn. Những thay đổi này không chỉ cải thiện hiệu suất và trải nghiệm người dùng mà còn giúp các nhà phát triển viết mã một cách trực quan và dễ dàng hơn.

Những cải tiến này cho thấy React đang liên tục phát triển và hoàn thiện, mang đến những công cụ mạnh mẽ và tiện lợi cho cộng đồng lập trình viên. Với các tính năng mới trong React 19, chúng ta có thể mong đợi những ứng dụng web ngày càng nhanh chóng, mượt mà và dễ quản lý hơn.

Ngoài ra bạn có thể tham khảo thêm một số hook khác tại đây

Avatar photo

Unity IAP: Triển khai Mua Hàng Consumable

Giới Thiệu Việc tích hợp tính năng mua hàng trong ứng dụng Unity là không thể tránh khỏi. Mua hàng trong ứng dụng có...
Avatar photo Tam Canh Le Chi
6 min read

Leave a Reply

Your email address will not be published. Required fields are marked *