Thứ năm, 12/12/2019 | 00:00 GMT+7

Tạo một sử dụng tùy chỉnhFetch () React Hook

Một móc tùy chỉnh là một hàm JavaScript có quy ước đặt tên duy nhất yêu cầu tên hàm bắt đầu use và có khả năng gọi các móc khác.

Ý tưởng đằng sau các móc tùy chỉnh là extract logic thành phần vào các chức năng có thể tái sử dụng.

Thông thường, khi ta xây dựng các ứng dụng React, ta thấy mình viết các mã chính xác gần như giống nhau trong hai hoặc nhiều thành phần khác nhau. Lý tưởng nhất là những gì ta có thể làm trong những trường hợp như vậy là extract logic lặp lại đó thành một đoạn mã có thể tái sử dụng (hook) và sử dụng lại nó khi cần thiết.

Trước hooks, ta đã chia sẻ logic trạng thái giữa các thành phần sử dụng đạo cụ kết xuất và các thành phần bậc cao hơn, tuy nhiên, kể từ khi giới thiệu hook và vì ta hiểu chúng tạo ra những khái niệm này gọn gàng như thế nào, việc tiếp tục sử dụng chúng sẽ không còn hợp lý nữa. Về cơ bản, khi ta muốn chia sẻ logic giữa hai hàm JavaScript, ta extract nó sang một hàm thứ ba có thể vì cả hai thành phần và hook đều chỉ là hàm.

Tìm nạp trừu tượng vào useFetch()

So với việc sử dụng API tìm nạp root ngoài hộp, 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 mã khai báo nhiều hơn, logic có thể tái sử dụng và mã 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 hook, được gọi là useEffect , tạo sẵn hai chức năng chính:

  1. Tìm nạp dữ liệu bằng API tìm nạp root .
  2. Đặt dữ liệu ở trạng thái local của thành phần với chức năng cập nhật của móc trạng thái.

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

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

Móc hiệu ứng chạy hai lần — khi thành phần mount và cập nhật. Điều này nghĩa là nếu không làm gì với ví dụ useFetch ở trên, bạn sẽ gặp phải một chu kỳ lặp lại. Điều này là do bạn đang cài đặt trạng thái sau mỗi lần tìm nạp dữ liệu. Kết quả là thành phần cập nhật và hiệu ứng chạy lại khi trạng thái được cài đặt .

Điều này sẽ dẫn đến một vòng lặp tìm nạp dữ liệu vô hạn. Để giải quyết vấn đề này, bạn chỉ nên tìm nạp dữ liệu khi thành phần mount . Cung cấp một mảng trống làm đối số thứ hai cho móc hiệu ứng, vì điều này sẽ ngăn nó kích hoạt khi cập nhật thành phần nhưng chỉ khi thành phần đượ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 phụ thuộc vào. Nếu bất kỳ biến nào thay đổi hook sẽ chạy lại. Nếu đối số là một mảng trống, hook sẽ không chạy khi cập nhật thành phần vì không có biến nào để xem.

useEffect 's Return Error

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

Theo thiết kế, bạn đã vi phạm luật này bởi vì mã không trả về không có gì và một lời hứa không xóa sạch bất cứ điều gì.

Nếu bạn sử dụng mã như vậy, bạn sẽ nhận được cảnh báo trong console chỉ ra thực tế là hàm useEffect phải trả về một hàm dọn dẹp hoặc không có gì.

Tóm lại, việc sử dụng các hàm không đồng bộ trực tiếp trong hàm useEffect() là điều không tốt. Bạn có thể giải quyết vấn đề này bằng cách viết và sử dụng hàm không đồng bộ bên trong hiệu ứng.

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 hàm effect, ta đã tạo một hàm async mới fetchData() để thực hiện thao tác tìm nạp và chỉ cần gọi hàm bên trong useEffect. Bằng cách này, ta tuân theo luật trả về không có gì hoặc chỉ là một hàm dọn dẹp trong một hiệu ứng hook. Và nếu bạn nên kiểm tra lại trên console , bạn sẽ không thấy bất kỳ cảnh báo nào nữa.

Xử lý lỗi

Một điều mà ta chưa đề cập cho đến nay là cách ta có thể xử lý các ranh giới lỗi trong khái niệm này. Khi sử dụng async / await, thông thường bạn sử dụng cấu trúc try/catch để xử lý lỗi cũng sẽ hoạt động ở đây.

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 }; }; 

Ở đây, bạn đã sử dụng cú pháp try / catch của JavaScript để đặt và xử lý các ranh giới lỗi. Bản thân lỗi chỉ là một trạng thái khác được khởi tạo bằng một hook trạng thái. Khi nào hook chạy, trạng thái lỗi sẽ được đặt lại. Tuy nhiên, khi nào có trạng thái lỗi, thành phần sẽ hiển thị phản hồi cho user . Điều này cho phép bạn thực hiện bất kỳ thao tác mong muốn nào với nó.

Đặt chỉ báo tải

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

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 };     }; 

Thể hiện các khái niệm bằng một ứng dụng

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

Đầu tiên, xác định useFetch() của bạn. Bạn sẽ sử dụng lại ví dụ đã tạo trong khi trình bày xử lý lỗi.

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 hàm useFetch() để yêu cầu dữ liệu 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 cho hàm useFetch() với một đối tượng tùy chọn trống để tìm nạp dữ liệu cho chú chó. Sau khi dữ liệu được tìm nạp, mã sẽ extract nó từ đối tượng phản hồi và hiển thị trên màn hình. Bạn có thể xem lại phần trình diễn trên CodeSandbox tại đây .

Kết luận

Tìm nạp dữ liệu luôn là một vấn đề phải đối mặt khi xây dựng các ứng dụng giao diện user . Trong hướng dẫn này, bạn đã thực hiện một bản demo nhỏ để xem cách bạn có thể tìm nạp dữ liệu một cách khai báo và hiển thị nó trên màn hình bằng cách sử dụng hook useFetch với API fetch() root .


Tags:

Các tin liên quan