Contents

Cách sử dụng các phím React để tránh xung đột thành phần

Khung React có thể đưa ra những thách thức phức tạp, dẫn đến các hành vi không lường trước được hoặc các lỗi khó nắm bắt khó giải quyết đối với những người thiếu hiểu biết về nguyên nhân gốc rễ của chúng.

Khi kết xuất một thành phần có điều kiện dựa trên các giá trị thuộc tính cụ thể, có thể xảy ra lỗi bất thường được gọi là lỗi"kết xuất có điều kiện của cùng một thành phần". Để tìm hiểu sâu hơn về vấn đề này và khám phá cách giải quyết vấn đề bằng cách sử dụng các phím React, hãy xem xét kỹ vấn đề.

Các thành phần phản ứng không phải lúc nào cũng độc lập

Cấu trúc đơn giản của React là lý do quan trọng giải thích tại sao bạn nên học thành thạo thư viện JavaScript này để xây dựng giao diện người dùng. Tuy nhiên, mặc dù có rất nhiều lợi ích liên quan đến việc sử dụng React, nhưng điều quan trọng là phải thừa nhận rằng nó có phần không hoàn hảo và khiếm khuyết.

Vấn đề được đề cập phát sinh từ trường hợp trong đó một thành phần được hiển thị ngẫu nhiên dựa trên các tiêu chí cụ thể, nhưng được cung cấp các thuộc tính không giống nhau trong quá trình khởi tạo.

React tận dụng thuật toán khác biệt DOM ảo của nó để chỉ cập nhật hiệu quả những phần của DOM thực đã thay đổi kể từ lần kết xuất trước đó. Chiến lược này được khẳng định dựa trên giả định rằng phần lớn các thay đổi xảy ra ở cấp độ của các yếu tố riêng lẻ trong hệ thống phân cấp, thay vì ở cấp độ cao nhất. Do đó, khi so sánh các thành phần anh em với đánh dấu giống hệt nhau và không có trạng thái cục bộ, thuật toán của React nhận ra chúng là tương đương và bỏ qua quá trình kết xuất lại của chúng. Do đó, bất kỳ trạng thái nào được xác định trong một trong những thành phần này vẫn tồn tại trong các lần hiển thị liên tiếp vì chúng không được làm mới.

Hãy để tôi cung cấp một diễn giải tinh tế hơn của tuyên bố đó. Giả sử chúng ta kiểm tra một thể hiện của bảng Thành phần sau:

 import { useState, useEffect } from "react"

export function Counter({name}) {
  const [count, setCount] = useState(0)

  return(
    <div>
      <div>{name}</div>
      <button onClick={() => setCount(c => c-1)}> - </button>
      <br />
      <button onClick={() => setCount(c => c \+ 1)}> \+ </button>
    </div>
  )
}

Thành phần “Counter” nhận thuộc tính được đặt tên từ thực thể mẹ của nó thông qua hành động giải cấu trúc đối tượng, đóng vai trò như một phương thức để kết hợp các thuộc tính trong ngữ cảnh của ứng dụng React. Thành phần này sau đó sẽ hiển thị chỉ định này trong phần tử div HTML. Ngoài ra, nó trình bày hai yếu tố giao diện-một yếu tố được thiết kế để giảm giá trị được lưu trữ trong trạng thái và yếu tố khác để tăng giá trị đó.

Đoạn mã nói trên, đặc biệt liên quan đến việc triển khai ứng dụng trong thành phần “Ứng dụng”, đã được đặt câu hỏi về vấn đề tiềm ẩn của nó. Cần lưu ý rằng không có trục trặc nào tồn tại trong đoạn mã được cung cấp; đúng hơn, nó nằm trong việc sử dụng biến “bộ đếm” trong thành phần “Ứng dụng” đã nói.

 import { useState } from "react"
import { Counter } from "./Counter"

export default function App() {
  const [isKingsley, setIsKingsley] = useState(true)

  return(
    <div>
      { isKingsley ? <Counter name="Kingsley"/> : <Counter name="Sally"/> }
      <br/>
      <button onClick={() => setIsKingsley(k => !k)}> Swap </button>
    </div>
  )
}

Theo mặc định, đoạn mã nói trên hiển thị phép liệt kê có tên là “Kingsley”. Tuy nhiên, nếu một người tăng tổng số đếm đã nói lên giá trị “năm” và sau đó nhấn vào thiết bị lập bảng “Hoán đổi”, nó sẽ nhanh chóng hiển thị một phép liệt kê thay thế có tên là “Sally.

Tuy nhiên, thách thức nằm ở chỗ bộ đếm không trở về trạng thái ban đầu là 0 sau khi nó đã được sắp xếp lại.

Vấn đề hiện tại phát sinh do thực tế là cả hai phiên bản thành phần đều hiển thị các bộ phần tử giống hệt nhau theo một trình tự cụ thể. Tuy nhiên, React không phân biệt được giữa bộ đếm “Kingsley” và “Sally” do thuộc tính dùng chung của chúng, cụ thể là thuộc tính “tên”. Rất tiếc, React không sử dụng sự khác biệt này để xác định sự khác biệt giữa các thành phần có giá trị thuộc tính tương đương.

Một giải pháp khả thi cho vấn đề hai bộ đếm được hiển thị chồng lên nhau là sửa đổi cấu trúc của Mô hình đối tượng tài liệu (DOM) để tạo cấu trúc cây riêng biệt cho hai bộ đếm. Cụ thể, người ta có thể đặt bộ đếm đầu tiên bên trong phần tử div và bộ đếm thứ hai bên trong phần tử phần. Bằng cách đó, hai phần tử sẽ được hiển thị riêng biệt, tránh chồng chéo. Tuy nhiên, việc triển khai cách tiếp cận như vậy đòi hỏi sự hiểu biết thấu đáo về DOM và các thuộc tính của nó.

 import { useState } from "react"
import { Counter } from "./Counter"

export default function App() {
  const [isKingsley, setIsKingsley] = useState(true)

  return (
    <div>
      { isKingsley ?
         (<div>
          <Counter name="Kingsley"/>
         </div>)
        :
         (<section>
          <Counter name="Sally"/>
         </section>)
      }
      <br />
      <button onClick={() => setIsKingsley(k => !k)}> Swap </button>
    </div>
  )
}

Hành vi của ứng dụng thay đổi khi nút “Kingsley” được nhấp và hoán đổi với một phần tử khác trong cây DOM. Điều này dẫn đến việc đặt lại trạng thái do sự không giống nhau giữa cấu trúc của cây DOM ban đầu và cây DOM đã sửa đổi.

“ ”, trong đó phần trong cùng chứa một phần tử duy nhất. Ngược lại, khi giá trị “isKingsley” chuyển đổi giữa sai và đúng, cấu trúc kết quả trải qua thay đổi từ “ ” thành “ ”, thay thế thẻ trong cùng bằng thẻ ngoài cùng bao gồm cả thành phần gốc và thành phần con của nó. Sự chuyển đổi cấu trúc này nhắc React tạo lại thành phần Counter bằng cách

Ngoài ra, có thể giải quyết vấn đề này mà không sửa đổi các thành phần cấu trúc cơ bản của mã HTML của một người. Cách tiếp cận này loại bỏ yêu cầu điều chỉnh định dạng để giải quyết vấn đề hiện tại một cách hiệu quả.

Sử dụng Phím để Kết xuất Thành phần Mới

Để React phân biệt giữa các thành phần trong quá trình kết xuất, nó dựa vào các phím. Do đó, khi trình bày các thành phần giống hệt nhau, cần phải gán một khóa riêng cho từng phiên bản để thông báo cho React về tính cá nhân của chúng.

Sửa đổi từng bộ đếm bằng cách thêm một khóa bổ sung, như sau:

 import { useState } from "react"
import { Counter } from "./Counter"

export default function App() {
  const [isKingsley, setIsKingsley] = useState(true)

  return(
    <div>
      { isKingsley ?
         <Counter key="Kingsley" name="Kingsley"/> :
         <Counter key="Sally" name="Sally"/>
       }
      <br/>
      <button onClick={() => setIsKingsley(k => !k)}> Swap </button>
    </div>
  )
}

Khi tăng giá trị của bộ đếm “Kingsley” và nhấp vào nút “Swap”, React tạo một phiên bản mới của bộ đếm và khôi phục trạng thái bên trong của nó về giá trị ban đầu bằng 0.

Khi kết xuất một mảng bao gồm nhiều phiên bản của một loại dữ liệu thống nhất trong React, nên sử dụng các khóa duy nhất để phân biệt giữa chúng. Điều này là do React thiếu khả năng phân biệt các phần tử riêng lẻ trong các mảng như vậy và việc gán các mã định danh riêng biệt thông qua các khóa đảm bảo rằng mỗi phiên bản được khuôn khổ nhận dạng duy nhất.

 export default function App() {
  const names = ["Kingsley", "John", "Ahmed"]

  return(
    <div>
      { names.map((name, index) => {
        return <Counter key={index} name={name} />
      })}
    </div>
  )
}

React sử dụng cấu trúc dữ liệu nội bộ được gọi là “bộ đếm” cho từng phần tử riêng lẻ trong một mảng được gán khóa. Điều này cho phép hệ thống phát hiện và cập nhật bất kỳ sửa đổi nào được thực hiện đối với mảng được liên kết trong thời gian thực.

Một trường hợp sử dụng khóa nâng cao khác

Bạn có thể sử dụng các khóa để thiết lập mối quan hệ giữa hai phần tử riêng biệt dựa trên giá trị của biến trạng thái. Nói cách khác, bạn có thể kết nối một thành phần đầu vào với nhiều thành phần khác nhau thay đổi theo điều kiện của biến trạng thái.

Để chứng minh, hãy tinh chỉnh thành phần Ứng dụng:

 import { useState } from "react"

export default function App() {
  const [isKingsley, setIsKingsley] = useState(true)

  return(
    <div>
      { isKingsley ? <div>Kingsley's Score</div> : <div>Sally's score</div> }
      <input key={ isKingsley? "Kingsley" : "Sally" } type="number"/>
      <br/>
      <button onClick={() => setIsKingsley(k => !k)}> Swap </button>
    </div>
  )
}

Bất cứ khi nào người dùng hoán đổi giữa các phần tử div được liên kết với Kingsley và Sally bằng cách nhấp vào nút, thuộc tính khóa của đầu vào sẽ tự động được sửa đổi từ “Kingsley” thành “Sally” hoặc ngược lại. Do đó, React yêu cầu tái tạo hoàn toàn phần tử đầu vào sau mỗi lần nhấn nút liên tiếp.

Các mẹo khác để tối ưu hóa ứng dụng React

Tối ưu hóa mã là điều cần thiết để cung cấp trải nghiệm thú vị cho người dùng trong cả ứng dụng web và thiết bị di động, vì nó đóng vai trò quan trọng trong việc đảm bảo ứng dụng chạy trơn tru và hiệu quả. Bằng cách tự làm quen với các kỹ thuật tối ưu hóa khác nhau, bạn có thể tối đa hóa hiệu suất của các ứng dụng dựa trên React của mình và nâng cao sự hài lòng chung của người dùng.

Các ứng dụng React Native, như ứng dụng web, cũng được hưởng lợi từ các chiến lược tối ưu hóa khác nhau. Một loạt các kỹ thuật nâng cao hiệu suất có thể được áp dụng để cải thiện chức năng và trải nghiệm người dùng của chúng.