Tìm hiểu cơ bản các Hook trong React hooks

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àm this.setState trong Class component
  • initStateValue: 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