useState trong React Component

Tram Ho

State

State là 1 khái niệm trong Class Component, trong Funcitonal Component chúng ta dùng useState

  1. state: định nghĩa tên của state nó có thể là đơn giá trị hoặc object
  2. setState: định nghĩa tên function dùng cho việc update state
  3. initialStateValue: là giá trị ban đầu của state.

code Typescript ta sẽ viết như này:

kiểu dữ liệu của State sẽ được khai báo luôn trong lúc tạo state: <string | undefined>

useState dùng để làm gì?

nó dùng để lưu lại giá trị bất kì được sử dụng trong Component

giá trị này sẽ bị kill khi Component này không còn được hiển thị nữa

useState nhận tham số gì?

tham số duy nhất nó nhận là giá trị khởi tạo của state

useState trả về gì?

nó trả về 1 cặp giá trị dưới dạng mảng [state, funciton để thay đổi state]

nếu không muốn update giá trị thì bỏ function đi cũng được:[state]

cách viết này áp dụng destructor của javascript bản mới

lưu ý khi dùng useState:

1. tại sao tôi phải dùng useState mà không khai báo biến bình thường trong Component? let state = initialStateValue; chẳng hạn?

về cơ bản, sử dụng hay không còn tùy vào trường hợp, sử dụng useState sẽ trả về 1 biến const, nó sẽ chặn phần nào việc thay đổi giá trị của state

việc sử dụng state sẽ cung cấp 1 đối tượng sống xuyên suốt thời gian sống của Component, còn biến thông thường thì không chắc

từng có trường hợp mình dùng let state = initialStateValue thay thế cho useState, kết quả là let state nhận về undifined

cụ thể mình không nhớ, cũng không hiểu tại sao nhưng rõ ràng là 1 bài học

mình thấy dùng useState vẫn tốt hơn khai báo let state, kiểu khai báo local này nên xài bên trong function thì hơn

2. tạo initialStateValue bằng callBack function

tại sao phải sử dụng cách này nhỉ?

tại 1 số trường hợp, giá trị khởi tạo không phải dễ tính toán như vậy, nhưng React phải đợi kết quả trả về rồi mới xử lý tiếp, việc này làm cho Project cảm giác như bị đơ vậy. Để tránh trường hợp như vậy có thể xem xét áp dụng trả về 1 callBack của việc tính toán này:

Lazy initial state

The initialState argument is the state used during the initial render.

In subsequent renders, it is disregarded.

If the initial state is the result of an expensive computation, you may provide a function instead

3. useState() use REPLACING instead of MERGING

nếu sử dụng setState(newVal) thì giá trị cũ sẽ bị mất đi, giá trị mới sẽ ghi đè lại giát trị cũ

đây sẽ chả phải vấn đề nếu giá trị không phải Object, sẽ có 2 trường hợp xảy ra

  1. bạn sẽ phải clone 1 Object mới từ Object cũ rồi update các giá trị cần thiết: setPerson({ …person, color: ‘green’ });
  2. vì state là Object nên có thể đổi giá trị bên trong Object 1 cách bình thường: person.color = ‘green’;

ưu nhược điểm:

  1. tính chất của setState là update chậm, có nghĩa là:

    line 10: setPerson({ ...person, color: 'green' });

    line 11: person -> data vẫn chưa được update

    nó sẽ còn chưa update cho đến khi tất cả các hàm đang chạy hiện tại chạy hết, trước khi re-gender thì nó mới update

    hãy áp dụng cách này nếu data sử dụng để hiển thị trên màn hình, không cần sử dụng ngay khi mới update

  2. việc sửa trực tiếp Object như này không thông qua hàm setState

    và dĩ nhiên là nó sẽ không trigger hàm re-gender trên màn hình hay các hook khác như useEffect chẳng hạn

    hãy sử dụng nếu muốn lấy giá trị mới để sử dụng luôn, áp dụng nhiều lúc submit chuẩn bị chuyển trang

Unlike the setState method found in class components, useState does not automatically merge update objects.
You can replicate this behavior by combining the function updater form with object spread syntax:

Another option is useReducer, which is more suited for managing state objects that contain multiple sub-values.

4. Cập nhật state sử dụng callback function

Thay vì cập nhật state bằng cách truyền vào giá trị mới, thì chúng ta có thể cập nhật state bằng cách truyền vào một hàm callback (có tham số là giá trị cũ) và trả về kết quả là giá trị mới. Ví dụ:

Dùng cách này thì khi cập nhật state sẽ đảm bảo giá trị mới phụ thuộc vào giá trị cũ chứ không phụ thuộc vào giá trị của state ở thời điểm hiện tại.
Ví dụ:

Nếu cập nhật state bằng cách trên thì khi người dùng bấm nút nhiều lần trong khoảng thời gian 3 giây, thì sau 3 giây giá trị của state cũng chỉ tăng lên 1:

Nếu cập nhật state bằng cách truyền vào một hàm thì trong 3 giây delay, người dùng bấm nút bao nhiêu lần thì giá trị của state sẽ tăng lên bấy nhiêu.

Như vậy tùy từng trường hợp mà chúng ta sẽ lựa chọn cách sử dụng sao cho hợp lý.

5. tại sao lại cần có <kiểu dữ liệu> trong useState<kiểu dữ liệu>(initialStateValue)

==> mục này không còn hoạt động tại thời điểm hiện tại, mình code demo thì không còn tái hiện được nữa, nhưng mọi người vẫn nên đọc tham khảo.

giả sử xét đối tượng:

sau khi call onChange, setMessage được gọi nhưng Object lúc này chỉ chứa message, và nó vẫn hoạt động bình thường, tất nhiên, id đã bị mất.

việc khai báo rõ ràng kiểu dữ liệu bên trong sẽ tránh được những lỗi như này

6. tại sao trong 1 useState thì state phải cho vào danh sách phụ thuộc của các Hook khác, nhưng setState thì không?

React guarantees that setState function identity is stable and won’t change on re-renders. This is why it’s safe to omit from the useEffect or useCallback dependency list.

hay nói cách khác, state thì có thể thay đổi, chứ hàm setState thì không thay đổi, và React cam kết điều này, nên trong các Dependency List, bạn sẽ phải thêm state để kiểm tra thay đổi chứ không phải là hàm setState

kết luận

  1. useState dùng để lưu dữ liệu trong suốt thời gian sống của Component
  2. hàm setState sẽ kích hoạt re-render, nhưng update giá trị chậm, sửa giá trị thông qua ref của Object thì không re-render, nhưng giá trị được sửa ngay lập tức
  3. initial State và update State đều có thể truyền vào callback function, nhưng nên để ý khi nào dùng, cẩn thận khó maintain
Chia sẻ bài viết ngay

Nguồn bài viết : Viblo