Hướng dẫn tạo useFetch() React Hook

Fetch API là một API đơn giản cho việc gửi và nhận requesst bằng Javascript. Với fetch thì việc thực hiện các yêu cầu web và xử lý phản hồi dễ dàng hơn so với XMLHttpRequest cũ. Hãy cùng lướt qua bài viết ngay nào


1041

Lớp trừu tượng fetch useFetch()

So với việc sử dụng fetch API bình thường, việc trừu tượng hóa nó vào hook useFetch mang lại cho nó khả năng một lớp lót, kiểu code khai báo dễ hơn, logic có thể sử dụng lại và code tổng thể sạch hơn. Hãy xem ví dụ useFetch này:

const useFetch = (url, options) => {
  const [response, setResponse] = React.useState(null);
  useEffect(async () => {
      const res = await fetch(url, options);
      const json = await res.json();
      setResponse(json);
  });
  return response;
};

Ở đây, hiệu ứng của hook, được gọi là useEffect, tạo thành hai hàm chính:

  1. Fetches dữ liệu với API .
  2. Gán dữ liệu ở state local của component với chức năng cập nhật state hook.

Bạn cũng sẽ nhận thấy rằng việc giải quyết promise xảy ra với async / await.

Tránh vòng lặp tham chiếu

Hook effect chạy trong hai lần, khi component gắn kết và cập nhật. Điều này có nghĩa là nếu không có gì thực hiện useFetch ở trên, bạn sẽ chạy vào một chu kỳ vòng lặp lặp lại. Điều này là do bạn đang đặt state sau mỗi lần fetch dữ liệu. Kết quả là, component cập nhật và effect chạy lại khi state được gán trên app React.

Điều này sẽ dẫn đến một vòng lặp fetching vô hạn. Để giải quyết vấn đề này, bạn chỉ nênfetch dữ liệu khi component mounts. Cung cấp một mảng trống làm argument( đối số) thứ hai cho hook effect, vì điều này sẽ ngăn nó kích hoạt trên component update nhưng chỉ khi component được mount.

useEffect(async () => {
    const res = await fetch(url, options);
    const json = await res.json();
    setResponse(json);
}, []); // empty array

Thứ hai là một mảng chứa tất cả các biến mà hook depends. Nếu bất kỳ biến nào thay đổi, hook sẽ chạy lại. Nếu argument là một mảng trống, hook sẽ không chạy khi component update vì không có biến nào để xem.

Sử dụng useEffect’s Return Error

Bạn có thể nhận thấy rằng bạn đang sử dụng async / await để fetch dữ liệu trong hook effect. Tuy nhiên, theo quy định về tài liệu, mọi chức năng được chú thích bằng async đều trả về promise ngầm. Vì vậy, trong hook effect của bạn, bạn đang trả về promise ngầm trong khi hook effect chỉ nên trả về không có gì hoặc function được dọn sạch app react.

Theo thiết kế, bạn đã vi phạm quy tắc này vì code không trả về gì cả và promise sẽ không làm sạch bất cứ điều gì.

Nếu bạn sử dụng code như hiện tại, bạn sẽ nhận được warning trong bảng console là hàm useEffect phải trả về function cleanup hoặc không có gì.

Để tóm tắt, việc sử dụng các hàm async trực tiếp trong hàm useEffect () được tán thành. Bạn có thể giải quyết vấn đề này bằng cách viết và sử dụng chức năng async bên trong effect.

React.useEffect(() => {
    const fetchData = async () => {
      const res = await fetch(url, options);
      const json = await res.json();
      setResponse(json);
    };
    fetchData();
  }, []);

Thay vì sử dụng hàm async trực tiếp bên trong function effect, chúng ta đã tạo một hàm async mới fetchData () để thực hiện thao tác fetch và chỉ cần gọi function bên trong useEffect.Bằng cách này, chúng ta tuân thủ quy tắc không trả lại bất cứ thứ gì hoặc chỉ là một function cleanup trong hook effect. Và nếu bạn nên kiểm tra lại trên bảng console, bạn sẽ không thấy bất kì warning nào

Handling Errors

Một điều chúng ta đã đề cập đến cho đến nay là cách handle error trong khái niệm này. Khi sử dụng async / await, thông thường sử dụng cấu trúc try / Catch để xử lý lỗi cũng sẽ hoạt động ở đây (app react).

const useFetch = (url, options) => {
  const [response, setResponse] = React.useState(null);
  const [error, setError] = React.useState(null);
  React.useEffect(() => {
    const fetchData = async () => {
      try {
        const res = await fetch(url, options);
        const json = await res.json();
        setResponse(json);
      } catch (error) {
        setError(error);
      }
    };
    fetchData();
  }, []);
  return { response, error };
};

Tại đây, bạn đã sử dụng cú pháp try/catch JavaScript để set và handle error. Bản thân lỗi chỉ là một trạng thái khác được khởi tạo với state hook. Bất cứ khi hook chạy, state lỗi được reset. Tuy nhiên, bất cứ khi nào có state lỗi, component sẽ phản hồi lại cho người dùng. Điều này cho phép bạn thực hiện bất kỳ hoạt động mong muốn với nó.

Setting Loading Indicators

Bạn có thể sử dụnghook để handle state loading cho các hoạt động fetch của mình. Nó là một biến state khác được quản lý bởi hook state. Điều này có nghĩa là nếu bạn muốn triển khai state loading trong ví dụ trước, bạn sẽ set biến state và update hàm useFetch () cho phù hợp trong app react.

const useFetch = (url, options) => {
  const [response, setResponse] = React.useState(null);
  const [error, setError] = React.useState(null);
  const [isLoading, setIsLoading] = React.useState(false);
  React.useEffect(() => {
    const fetchData = async () => {
      setIsLoading(true);
      try {
        const res = await fetch(url, options);
        const json = await res.json();
        setResponse(json);
        setIsLoading(false)
      } catch (error) {
        setError(error);
      }
    };
    fetchData();
  }, []);
  return { response, error, isLoading };
    };

Demonstrating Concepts với App

Bước này sẽ bao gồm demonstration thực hành để đưa các khái niệm này vào thực tế. Để làm điều này, bạn xây dựng app lấy hình ảnh con chó và tên của chúng. Bạn có thể sử dụng Fetch để gọi Dog API cho dữ liệu này của app.

Đầu tiên, xác định hàm useFetch () của bạn. Bạn sẽ sử dụng lại ví dụ được tạo trong khi tạo error handling.

const useFetch = (url, options) => {
  const [response, setResponse] = React.useState(null);
  const [error, setError] = React.useState(null);
  React.useEffect(() => {
    const fetchData = async () => {
      try {
        const res = await fetch(url, options);
        const json = await res.json();
        setResponse(json);
      } catch (error) {
        setError(error);
      }
    };
    fetchData();
  }, []);
  return { response, error };
};

Tiếp theo, tạo hàm App () sẽ sử dụng functionuseFetch () để yêu cầu dữ liệu các chú chó:

function App() {
  const res = useFetch("https://dog.ceo/api/breeds/image/random", {});
  if (!res.response) {
    return <div>Loading...</div>
  }
  const dogName = res.response.status
  const imageUrl = res.response.message
  return (
    <div className="App">
      <div>
        <h3>{dogName}</h3>
        <div>
          <img src={imageUrl} alt="avatar" />
        </div>
      </div>
    </div>
  );
}

Trong ví dụ này, bạn đã chuyển URL tới hàm useFetch () với đối tượng tùy chọn trống để fetch cho chú chó. Sau khi dữ liệu được fetch, code sẽ trích xuất nó từ đối tượng được response và hiển thị nó trên màn hình. Bạn có thể xem lại demonstration trên CodeSandbox tại đây.

Kết luận

Fetch dữ liệu luôn là một vấn đề cần phải giải quyết khi xây dựng các app frontend. Trong hướng dẫn này, bạn đã tạo một bản demo nhỏ để xem cách bạn có thể fetch dữ liệu và hiển thị dữ liệu trên màn hình bằng cách sử dụng hook useFetch với React API fetch () gốc.

Tham khảo thêm React tại đây : Sử dụng React-Lottie thêm animation cho web React


Like it? Share with your friends!

1041