Những lỗi React cần tránh để phát triển app thành công

React là một framework phổ biến, dễ học nhưng cũng dễ mắc lỗi khi lập trình nếu bạn không cẩn thận. Dưới đây là những lỗi React phổ biến mà bạn có thể mắc phải trong quá trình phát triển ứng dụng.

Lỗi lập trình React

Dùng sai kiểu hàm callback

Xử lý sự kiện là một tác vụ phổ biến trong React, qua tính năng lắng nghe sự kiện mạnh mẽ của JavaScript. Có thể bạn muốn thay đổi màu của nút bấm khi trỏ chuột qua hoặc gửi dữ liệu biểu mẫu tới server khi gửi. Ở cả hai trường hợp, bạn đều cần chuyển một hàm callback tới sự kiện để thực hiện phản ứng mong muốn. Đây là nơi một số lập trình viên React thường mắc lỗi.

Ví dụ:

export default function App() {
  function handleSubmit(e) {
    e.preventDefault()
    console.log("Form submitted!")
  }

  function print(number) {
    console.log("Print", number)
  }

  function doubler(number) {
    return () => {
      console.log("Double", number * 2)
    }
  }

  return (
    <>
      {/* Code will go here */}
    </>
  )
}

Tại đây, bạn có 3 hàm riêng biệt. Hai hàm đầu tiên không trả về kết quả, hàm thứ ba trả về hàm khác. Bạn phải nhớ rằng nó sẽ là chìa khóa để hiểu điều bạn sẽ học tiếp theo.

Giờ, chuyển sang JSX, bắt đầu với hàm đầu tiên và cách phổ biến nhất là chuyển một hàm làm trình xử lý sự kiện:

<form onSubmit={handleSubmit}>
  <input type="text" name="text" defaultValue="initial"/>
  <button>Submit</button>
</form>

Ví dụ chuyển tên của hàm tới sự kiện này qua thuộc tính onSubmit, nhờ đó, React gọi handleSubmit khi bạn gửi biểu mẫu. Bên trong handleSubmit, bạn có thể truy cập đối tượng sự kiện, cấp quyền vào thuộc tính như event.target.value cùng các phương thức như event.preventDefault().

Cách khác để chuyển một trình xử lý sự kiện là gọi nó bên trọng hàm callback. Về cơ bản, bạn đang chuyển onClick một hàm gọi print() cho bạn:

{[1, 5, 7].map((number) => {
  return (
    <button key={number} onClick={() => print(number)}>
      Print {number}
    </button>
  )
})}

Phương thức trên hữu ích trong những trường hợp mà bạn muốn chuyển dữ liệu cục bộ tới hàm này. Ví dụ chuyển từng số tới hàm print(). Nếu đã dùng phương thức đầu tiên, bạn không thể chuyển các đối số vào hàm này.

Phương pháp thứ ba là nơi mà rất nhiều lập trình viên mắc lỗi. Nhớ rằng hàm nhân đôi trả về hàm khác:

function doubler(number) {
  return () => {
    console.log("Double", number * 2)
  }
}

Giờ nếu đã dùng nó trong JSX như sau:

{[1, 5, 7].map((number) => {
  return (
    <button key={number} onClick={() => doubler(number)}>
      Double {number}
    </button>
  )
})}

Ở đây, hàm mà bạn trả về từ double() sẽ được gắn vào onClick. Về cơ bản, nó giống như việc sao chép chức năng được trả về và dán nó vào bên trong onClick. Nhìn chung, bạn nên thêm hàm dưới dạng biến (giống cách 1) và gọi hàm bên trong callback (cách 2).

Tất cả 3 cách trên đều hợp lệ bởi bạn đang chuyển một hàm tới sự kiện này. Trong React, bạn cần đảm bảo bạn chuyển một hàm tới thuộc tính event. Nó có thể là một biến, một hàm được mã hóa cứng (nội tuyến) hoặc một đối tượng/hàm mà trả về hàm khác.

Cho kết quả 0 trong khi kiểm tra lỗi

Khi xuất một phần tử có điều kiện trong React, bạn có thể dùng lệnh if…else hoặc kỹ thuật short-circuiting (đoản mạch). Short-circuiting liên quan tới cách dùng ký hiệu hai dấu và (&&). Nếu điều kiện trước dấu và đánh giá là true, trình duyệt chạy code theo dấu &. Nếu không, trình duyệt không chạy code.

Short-circuiting là kỹ thuật tốt hơn nhờ cú pháp chính xác, nhưng nó đi kèm với một hiệu ứng phụ mà nhiều lập trình viên không nhận ra. Lỗi này xảy ra do không hiểu chính xác cách JSX hoạt động với các giá trị giả.

Xem xét ví dụ sau:

export default function App() {
  const array = [1, 2, 3, 4]

  return (
    <div>
      {array.length && (
        <div>
          <span>Array items:</span> {array.join(", ")}
        </div>
      )}
    </div>
  )
}

Miễn là mảng có bên trong nó, React sẽ in từng mục trên trang. Đây là do kiểm tra array.length đang trả về một giá trị đúng. Thế nhưng, điều gì xảy ra khi mảng trống? Đầu tiên, các phần tử tiếp theo sẽ hiện trên trang đúng như bạn mong đợi. Tuy nhiên, bạn sẽ thấy một số 0 kỳ lạ hiện trên màn hình.

Nguyên nhân do array.length trả về số 0. Giá trị 0 là giả trong JavaScript. Và vấn đề ở đây là JSX xuất số 0 trên màn hình. Giá trị giả khác như null, false và undefined không được xuất. Đôi khi điều này có thể dẫn tới trải nghiệm xấu tới người dùng bởi số 0 luôn hiện trên trang. Thỉnh thoảng 0 có thể quá nhỏ tới mức bạn không nhận ra.

Giải pháp ở đây là đảm bảo chỉ trả về null, undefined hoặc false. Bạn làm việc này bằng cách kiểm tra rõ ràng số 0 trong điều kiện thay vì dựa vào một giá trị giả:

export default function App() {
  const array = [1, 2, 3, 4]

  return (
    <div>
      {array.length !== 0 && (
        <div>
          <span>Array items:</span> {array.join(", ")}
        </div>
      )}
    </div>
  )
}

Giờ giá trị 0 sẽ không hiện trên màn hình, ngay cả khi mảng trống.

Lỗi cập nhật trạng thái

Khi update trạng thái trong thành phần React, bạn cần làm việc đó đúng cách để tránh tác động không mong muốn. Lỗi tệ nhất là không có lỗi nào cho bạn, gây khó khăn trong việc gỡ lỗi và xác định lỗi đó là gì. Thất bại khi cập nhật trạng thái cũng gây ra ảnh hưởng này.

Lỗi này bắt nguồn từ việc không hiểu cách update trạng thái khi đang dùng trạng thái hiện tại. Hãy xem xét code mẫu. Ví dụ:

export default function App() {
  const [array, setArray] = useState([1, 2, 3])

  function addNumberToStart() {
    array.unshift(number)
    setArray(array)
  }

  function addNumberToEnd() {
    array.unshift(number)
    setArray(array)
  }

  return (
    <>
      {array.join(", ")}
      <br />
      <button
        onClick={() => {
          addNumberToStart(0)
          addNumberToEnd(0)
          console.log(array)
        }}
      >
        Add 0 to Start/End
      </button>
    </>
  )
}

Nếu đang chạy code trên, bạn sẽ thấy cả hai hàm đều được thêm 0 vào lúc bắt đầu và kết thúc của mảng. Thế nhưng, nó không có thêm 0 vào mảng được in trên trang. Bạn có thể liên tục click nút bấm này, nhưng UI vẫn giữ nguyên.

Nguyên nhân do ở cả hai hàm, bạn đang thay đổi trạng thái bằng array.push(). React cảnh báo rõ ràng rằng trạng thái phải bất biến trong React, nghĩa là bạn không thể thay đổi nó. React dùng các giá trị tham chiếu với trạng thái này.

Giải pháp ở đây là truy cập trạng thái hiện tại (currentArray), tạo bản sao trạng thái và bản cập nhật cho bản sao đó:

function addNumberToStart(number) {
  setArray((currentArray) => {
    return [number, ...currentArray]
  })
}

function addNumberToStart(number) {
  setArray((currentArray) => {
    return [...currentArray, number]
  })
}

Đây là phương thức đúng để update trạng thái trong React. Giờ khi bạn click vào nút bấm, nó thêm số 0 vào phần đầu và kết thúc của mảng. Nhưng quan trọng nhất ở đây là các bản update sẽ phản ánh ngay lập tức trên trang.

Trên đây là những lỗi lập trình React cần tránh. Hi vọng bài viết hữu ích với các bạn.

Thứ Tư, 17/05/2023 12:56
51 👨 143
0 Bình luận
Sắp xếp theo