- vừa được xem lúc

useState trong React Component

0 0 10

Người đăng: vĩnh đặng văn

Theo Viblo Asia

State

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

const [state, setState] = useState(initialStateValue);
  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:

const [state, setState] = useState<string | undefined>(initialStateValue);

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:

const result = () => expensiveComputation();
const [state, setState] = useState<string>(result);

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:

setState(prevState => { // Object.assign would also work return {...prevState, ...updatedValues};
});

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ụ:

setCount(prevCount => prevCount + 1)

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:

function handleClick() { setTimeout(() => { setCount(count + 1); // Thay đổi state dựa theo giá trị của state hiện tại }, 3000);
}

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.

function handleClick() { setTimeout(() => { setCount(prevCount => prevCount + 1); // Thay đổi state dựa theo giá trị của state trước đó }, 3000);
}

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:

const [messageObj, setMessage] = useState({ message: '', id: 1 });
onChange={e => { const newMessageObj = { message: e.target.value }; setMessage(newMessageObj); }}
<strong>{messageObj.id} : {messageObj.message}</strong>

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

Bình luận

Bài viết tương tự

- vừa được xem lúc

Những điều cần lưu ý và sử dụng Hook trong React (Phần 5)

V. Sử dụng useRef như thế nào cho đúng.

0 0 127

- vừa được xem lúc

7 Cách viết code React "clean" hơn

Mở đầu. Là nhà phát triển React, tất cả chúng ta đều muốn viết code sạch hơn, đơn giản hơn và dễ đọc hơn. 1. Sử dụng JSX shorthands.

0 0 188

- vừa được xem lúc

Create app covid-19 use Reactjs

Chào các bạn hôm nay mình sẽ chia sẻ với các bạn một app covid-19, để mọi người cùng tham khảo, tính năng của App này chỉ đơn giản là show số liệu về dịch Covid của các nước trên thế giới như: Số ngườ

0 0 39

- vừa được xem lúc

ReactJS Custom Hooks

ReactJS cung cấp rất nhiều cho bạn các hook mà bạn có thể sử dụng hằng ngày vào project của mình. Nhưng bên cạnh đó bạn có thể tự tạo ra các hook của riêng bạn để sử dụng, làm cho việc tối ưu hóa code

0 0 65

- vừa được xem lúc

3 cách để tránh re-render khi dùng React context

3 cách để tránh re-render khi dùng React context. Nếu đã từng sử dụng React context cho dự án của bạn, và gặp phải tình trạng các component con - Consumer re-render rất nhiều lần, thậm chí bị sai logi

0 0 25

- vừa được xem lúc

Tìm hiểu về React Hook: Sử dụng useDebugValue

Trong bài viết hôm này, tôi sẽ giới thiệu các bạn một React Hook tiếp theo, đó là useDebugValue. useDebugValue là gì .

0 0 45