× Giới thiệu Lịch khai giảng Tin tức Sản phẩm học viên

Effect & Ref trong reactjs - Tìm hiểu nhanh trong 5 phút

18/03/2024 01:33

Cũng giống như API useState, React có một số API khác (còn gọi là hook). Hai trong số các API/hook đó có liên quan đến ứng dụng file.io

Cũng giống như API useState, React có một số API khác (còn gọi là hook). Hai trong số các API/hook đó có liên quan đến ứng dụng file.io mà chúng ta sẽ di chuyển trong phần tiếp theo:

useEffect : Được sử dụng rộng rãi để thực hiện lệnh gọi API, nhưng cũng có thể được sử dụng để thực hiện bất kỳ tác dụng phụ nào như cập nhật DOM theo cách thủ công, đọc bộ nhớ cục bộ, v.v. Đối với ứng dụng của chúng tôi, chúng tôi sẽ sử dụng useEffect để thực hiện lệnh gọi API.

useRef : React Hook cho phép bạn tham chiếu một giá trị không cần thiết để hiển thị. Đối với ứng dụng của chúng tôi, chúng tôi sẽ sử dụng useRef để thao tác DOM (mô phỏng các nhấp chuột).

sử dụngHiệu ứng

hook useEffect là một React Hook cho phép bạn đồng bộ hóa một thành phần với hệ thống bên ngoài. Về cơ bản, useEffect được sử dụng để thực hiện lệnh gọi API. Ngoài ra, useEffect cũng có thể được sử dụng để thực thi một số mã chỉ khi hiển thị ban đầu.

API useEffect nhận một đầu vào bắt buộc và một đầu vào tùy chọn:

Hàm thực thi : Đây là đầu vào bắt buộc. Điều này chỉ định nhiệm vụ cho useEffect.

Các phần phụ thuộc : Điều này chỉ định khi nào hàm có trong useEffect sẽ thực thi. Nó có nên thực thi mỗi khi thành phần được hiển thị không? Nó có nên thực thi khi có gì đó thay đổi (như trạng thái) không?

Giả sử bạn mở một trang dựa trên React. Sau đây là các bước sơ bộ được thực hiện:

Thành phần có dữ liệu trống/mặc định sẽ được hiển thị

hook useEffect sẽ chạy lệnh gọi API tới một số hệ thống bên ngoài

Dữ liệu trả về sẽ được sử dụng để cập nhật trạng thái

Cập nhật trạng thái sẽ khiến thành phần hiển thị lại

Đây là dòng chảy trực quan:

 

Bạn có thấy vòng lặp vô hạn nào ở đây không? Kết xuất thành phần thực thi hiệu ứng. Hiệu ứng cập nhật trạng thái. Trạng thái mới kích hoạt kết xuất lại. Việc kết xuất lại thực thi hiệu ứng. Và như thế.

Đây là lý do tại sao việc thực thi hook useEffect cần phải được kiểm soát để chạy chính xác một lần ở lần hiển thị ban đầu hoặc chạy khi có gì đó thay đổi trong thành phần.

Cách tiêu chuẩn để chạy hiệu ứng chính xác một lần là cung cấp một mảng phụ thuộc trống làm đối số thứ hai ([]). Điều này sẽ đảm bảo rằng React chạy hiệu ứng chính xác một lần.

Hãy lấy một ví dụ để hiểu rõ hơn về useEffect hook.

Vấn đề

Viết một ứng dụng hiển thị một trò đùa ngẫu nhiên trên mỗi lần làm mới trang.

Giải pháp

Đây là một ứng cử viên tuyệt vời cho hiệu ứng. Chúng tôi muốn tìm một câu chuyện cười mới mỗi lần làm mới trang. Một JSX sẽ được xác định sử dụng trạng thái. Một hiệu ứng sẽ được cung cấp để chạy đúng một lần. Hiệu ứng sẽ cập nhật trạng thái. Điều này sẽ gây ra hiện tượng hiển thị lại thành phần sẽ hiển thị trò đùa trên trang. Hiệu ứng sẽ không thực thi khi hiển thị lại do danh sách phụ thuộc trống ([]).

LƯU Ý QUAN TRỌNG:

Với React v18, chức năng hiệu ứng sẽ chạy hai lần nếu sử dụng chế độ nghiêm ngặt trong chế độ phát triển. Vì chúng tôi đang sử dụng chế độ phát triển cho công việc này nên chúng tôi phải xóa chế độ nghiêm ngặt khỏi index.js:

 
// Old code

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// New code

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <App />
);

Trở lại vấn đề trò đùa, trò đùa được tìm nạp có hai phần: bố cục và phần kết. Chúng ta có thể sử dụng một đối tượng JS để lưu chúng vào một biến trạng thái duy nhất.

 
import React from "react";
import "./App.css";

function App() {
  const [joke, setJoke] = React.useState({});

  React.useEffect(() => {
    fetch("https://official-joke-api.appspot.com/random_joke")
      .then((resp) => resp.json())
      .then((data) => setJoke(data));
  }, []);

  return (
    <div className="App">
      <h1>{joke.setup}</h1>
      <h3>{joke.punchline}</h3>
    </div>
  );
}

export default App;

Mã tương tự với một số chú thích hữu ích là:

 
 

Trước khi kết thúc effect hook, hãy giải quyết thêm một vấn đề nữa yêu cầu chạy useEffect trên một lựa chọn thả xuống (một trường hợp sử dụng rất phổ biến khác).

Vấn đề

Viết một ứng dụng hiển thị giá tiền điện tử cho một loại tiền tệ nhất định. Danh sách các loại tiền tệ có thể được cung cấp dưới dạng dữ liệu tĩnh. Sử dụng bitcoin làm tiền tệ mặc định.

Giải pháp

Trong ứng dụng này, hiệu ứng cần được gọi hai lần:

  •  

    Khi làm mới trang, hiển thị giá hiện tại cho loại tiền mặc định (Bitcoin)

    Khi lựa chọn thả xuống, hiển thị giá cho loại tiền đã chọn

Chúng ta có thể sử dụng hai hiệu ứng cho việc này

Hiệu ứng thứ nhất : Được gọi khi tải trang, trong đó hiệu ứng đặt danh sách thả xuống thành bitcoin. Danh sách phụ thuộc sẽ là [] để chỉ chạy một lần.

Hiệu ứng thứ hai : Được gọi khi lựa chọn thả xuống thay đổi. Cái này thực hiện lệnh gọi API bên ngoài. Danh sách phụ thuộc sẽ là trạng thái để hiệu ứng này diễn ra khi có sự thay đổi trạng thái.

Một danh sách tĩnh các loại tiền tệ được hỗ trợ được duy trì trong thành phần. Khi chọn một tùy chọn, trạng thái sẽ được cập nhật sẽ kích hoạt hiệu ứng, trạng thái này sẽ cập nhật giá trong trạng thái đó. Hiệu ứng được cấu hình để chỉ chạy khi id và tên bên trong trạng thái thay đổi. Hiệu ứng sẽ không chạy khi giá bên trong trạng thái thay đổi. Điều này cung cấp khả năng kiểm soát chi tiết đối với việc thực hiện hiệu ứng.

Mã của ứng dụng là

import React from "react";
import "./App.css";

function App() {
  const currencies = [
    { id: 90, name: "Bitcoin" },
    { id: 80, name: "Ehtereum" },
    { id: 58, name: "XRP" },
    { id: 2, name: "Dogecoin" },
    { id: 1, name: "Litecoin" },
    { id: 2321, name: "Bitcoin Cash" },
  ];
  const [currency, setCurrency] = React.useState({
    name: "",
    id: 0,
    price: 0,
  });

  React.useEffect(() => setCurrency({ ...currencies[0] }), []);

  React.useEffect(() => {
    fetch(`https://api.coinlore.net/api/ticker/?id=${currency.id}`)
      .then((resp) => resp.json())
      .then((data) =>
        setCurrency((prev) => {
          return { ...prev, price: data[0].price_usd };
        })
      )
      .catch(() => {});
  }, [currency.name, currency.id]);

  function updateCurrency(event) {
    const currencyName = event.target.options[event.target.selectedIndex].text;
    setCurrency({ name: currencyName, id: event.target.value, price: 0 });
  }

  return (
    <div className="App">
      <select onChange={updateCurrency} className="currency-list">
        {currencies.map((v, index) => (
          <option key={index} value={v.id}>{v.name}</option>
        ))}
      </select>
      <br />
      <h1>{currency.name}</h1>
      {currency.price !== 0 && <h3>{currency.price} USD</h3>}
    </div>
  );
}

export default App;

Hãy dành chút thời gian và xem xét mã một cách chi tiết. Điều quan trọng là hiệu ứng đầu tiên không phụ thuộc vào gì cả nên nó chạy đúng một lần. Hiệu ứng này sẽ loại bỏ loại tiền tệ đầu tiên ra khỏi danh sách các loại tiền tệ được hỗ trợ và cập nhật trạng thái. Sự thay đổi trạng thái kích hoạt hiệu ứng thứ hai vì hiệu ứng thứ hai phụ thuộc vào những thay đổi về tên và id trong trạng thái. Hiệu ứng thứ hai thực hiện lệnh gọi API và cập nhật giá ở trạng thái. Điều này kích hoạt hiển thị thành phần, nhưng hiệu ứng thứ hai không chạy lại vì nó chỉ phụ thuộc vào thay đổi id và tên. Một sơ đồ có thể giúp hiểu nó tốt hơn:

 

Hãy thử nghiệm nó:

 

Đó là tất cả về hook hiệu ứng. Kiến thức nhiều về hook này là đủ để viết ứng dụng file.io. Và, ý tưởng nhiều về hiệu ứng này cũng đủ cho hầu hết công việc hàng ngày.

 
sử dụngRef

Hook useRef cho phép bạn duy trì các giá trị giữa các lần hiển thị. Nó có thể được sử dụng để lưu trữ một giá trị có thể thay đổi mà không gây ra hiện tượng hiển thị lại khi cập nhật. Nó có thể được sử dụng để truy cập trực tiếp vào phần tử DOM. Móc useRef có một số trường hợp sử dụng nâng cao. Đối với ứng dụng file.io, chúng tôi sẽ sử dụng useRef để mô phỏng các lượt nhấp chuột. Câu hỏi đặt ra là tại sao chúng ta muốn thao tác trực tiếp với DOM?

 
import React from "react";
import "./App.css";

function App() {

  return (
    <div className="App">
      <input type="file" className="file"></input>
    </div>
  );
}

export default App;