Tìm hiểu cơ bản các Hook trong React hooks
Khi làm việc với các React Component chúng ta cần phải thao tác rất nhiều với state, props hay life cycle. Và kể từ phiên bản 16.8 trở đi React cung cấp một chức năng mới đó là React hooks, chức năng này cho phép thay thế việc sử dụng state thông thường bằng các khái niệm mới như useState, useEffect, ...
Trong bài viết này, tôi muốn giới thiệu đến một số Hook cơ bản:
- useState
- useEffect
- useMemo
- useCallback
1. useState
Trong Class Component cho phép khai báo khai báo local state. Khi React phát triển và cung cấp React hooks cho phép chúng ta làm điều đó trong Function Component.
const [state, setState] = useState(initStateValue)
Trong đó:
-
state
: được định nghĩa là giá trị của biến có thể là một giá trị hoặc một object, array, ... setState
: được sử dụng để update state. Nó tương tự với hàmthis.setState
trong Class componentinitStateValue
: giá trị được khởi tạo ban đầu của state
Ví dụ về khai báo và sử dụng useState
trong Function Component
const getName = () => {
const [name, setName] = useState(" ")
return (
<div>
<input value={name} onChange={e=>setName(e.target.value)} type="text">
</div>
)
}
//giá trị ban đầu: " "
//giá trị sau khi nhập input: "Haposoft"
Chúng ta có thể khai báo nhiều state trong 1 function component
const function = () => {
const [value, setValue] = useState(0)
const [value1, setValue1] = useState(0)
...
}
Khi có nhiều state thì ta sẽ khai báo các dòng state khác nhau. Điều này đúng nhưng nó gây ra những nhầm lẫn và rối khi sử dụng state ở project lớn. Những trường hợp như vậy chúng ta nên sử dụng Object để khai báo giá trị của State như vậy nó sẽ đỡ rối hơn.
const function = () => {
const [state, setState] = useState({value:1, value1: 2});
...
}
Nó giống với Class Component khai báo state. Với Class Component thì hàm setState
sẽ merged giá trị vào State còn Function Component thì không nó sẽ Replace.
2. useEffect
useEffect
được sử dụng với mục đích quản lý vòng đời của một component trong function component thay vì các lifecycle phức tạp trong class component
useEffect(effectFunction, arrayDependencies)
với đối số thứ nhất useEffect
trong function component thì effectFunction
sẽ được thực thi khi component được render xong. Tương tự như componentDidUpdate
const func = () => {
const [count, setCount] = useState(0)
const handleClick = () => setCount(count + 1)
useEffect(() => {
return () => document.title = 'Count is: ' + count
})
return <div>
<button onClick={handleClick}>Increment Count</button>
</div>
}
đối số thứ 2 là arrayDependencies
khi thay đổi thì đối số thứ nhất mới thực thi effectFunction
vậy nếu arrayDependencies
không thay đổi tức ta gán bằng []
thì điều này có nghĩa nó tương đương với componentDidMount
vì khi này function trong useEffect
chỉ gọi 1 lần.
const func = () => {
const [count, setCount] = useState(0)
const handleClick = () => setCount(count + 1)
useEffect(() => {
return () => document.title = 'Count is: ' + count
}, [])
return <div>
<button onClick={handleClick}>Increment Count</button>
</div>
}
3. useMemo
useMemo
là một react hooks giúp mình tạo ra một memoized value và chỉ tính toán ra value mới khi dependencies thay đổi.
- Nhận vào 2 tham số: 1 là function, 2 là dependencies.
- Return memoized value
- Chỉ tính toán value mới khi dependencies thay đổi.
- Nếu dùng empty dependencies thì không bao giờ tính toán lại value mới.
const func = useMemo((function),[dependencies])
Nó sẽ memorizes value output của một function và chỉ recomputed memoried value này khi mà một trong các dependencies thay đổi. Nói cách khác thì useMemo
sẽ lưu giá trị trả về của function và nó sẽ kiểm tra xem phụ thuộc thay đổi thì nó mới chạy hàm phía trong, còn không thì sẽ trả về value đã cached trước đó
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
Bản thân hook giới thiệu là một logic phức tạp, nó có thể gây ra nhiều vấn đề về hiệu xuất hơn là cách nó giải quyết. Không áp dụng useMemo
trừ khi đây là tính toán thực sự mất nhiều công sức.
Theo tài liệu React useMemo, bạn có thể không bao giờ phụ thuộc vào các cơ chế trên useMemo
. Nói cách khác, mặc dù useMemo
chỉ được gọi khi callback thay đổi, nhưng điều này không đảm bảo. Ứng dụng của bạn vẫn phải hoạt động, hoàn thành tốt (Mặc dù có thể chậm trễ) nếu useMemo
gọi lại cho bạn mỗi lần hiển thị.
4. useCallback
useCallback
là một react hooks giúp mình tạo ra một memoized callback và chỉ tạo ra callback mới khi dependencies
thay đổi.
- Nhận vào 2 tham số: 1 là function, 2 là
dependencies
. - Return memoized callback.
- Chỉ tạo ra function mới khi
dependencies
thay đổi. - Nếu dùng empty dependencies thì không bao giờ tạo ra function mới.
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
Ví dụ về useCallback
const increase = useCallback(() => setCount(count + 1), [count]);
const decrease = useCallback(() => setCount(count - 1), [count]);
const increaseOther = useCallback(() => setCountOther(countOther + 1), [countOther]);
const decreaseOther = useCallback(() => setCountOther(countOther + 1), [countOther]);
useCallback
cũng sỡ hữu nhược điểm,, chủ yếu là độ phức tạp của mã. Ở đây có rất nhiều trường hợp không hợp lý khi thêm useCallback
và chúng ta phải chấp nhận để hàm khởi tạo lại. Như đã nói, useCallback
cũng sở hữu nhược điểm về hiệu xuất, vì nó vẫn phải chạy trên mọi thành phần render
.
6. Tổng kết
Ngoài những hook cơ bản hay được sử dụng mà mình đã giới thiệu ở trên thì vẫn còn 1 số hook khác như là useContext
, useRef
, useLayoutEffect
, useDebugValue
, useImperativeHandle
các bạn có thể vào trang chủ của react hooks để tìm hiểu thêm nhé.
Để có thể sử dụng hooks một cách hiệu quả và tối ưu nhất thì mọi người hãy lưu ý rằng hạn chế sử dụng hooks trong các vòng lặp hay nested function bởi vì như vậy nó sẽ làm mất đi tính đúng đắn của hooks. Một điều nữa là bạn chỉ nên gọi hooks trong React component, đừng gọi hooks trong một function javascript thông thường.
Nguồn tham khảo:
https://reactjs.org/docs/hooks-reference.html
https://viblo.asia/p/cung-tim-hieu-ve-cac-hook-trong-react-hooks-Ljy5VYgjlra?fbclid=IwAR2JlE6uJwN2trvWEgX3_hPNZSlWPuvvW5P8GhKrCDqT53xv7_v4GrQITTI
https://reactjs.org/docs/hooks-overview.html