Avatar

Huy Pham

19/03/2022|6 phút đọc
0
0

React Hooks là gì? Các hooks thường dùng trong ReactJS?

Trong bài viết này chúng ta sẽ cùng nhau tìm hiểu về React Hooks và các hooks thường dùng trong ReactJS.

react-hook.jpg

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..

1. Giới thiệu về React Hooks

Vậy thì React Hooks thực sự nó là gì!?

Chúng ta có thể hiểu React Hooks là một chức năng được xây dựng trong React cho phép chúng ta có thể sử dụng state và life cycle bên trong một functional components.

Hooks đem lại một vài lợi ích khi làm việc như :

  • Cải thiện hiệu suất làm việc bằng cách có thể tái sử dụng code.
  • Các thành phần được trình bày khoa học hơn.
  • Sử dụng một cách linh hoạt trong component tree.

React Hooks đem lại cho functional components các tính năng cần thiết của component, nó có thể thay thế gần như hoàn toàn việc sử dụng class components. Ở đây mình có ví dụ để chứng minh điều đó.

Ở ví dụ này, mình xây dụng một component counter, có state là một number, có thể onClick để tăng hoặc giảm giá trị của state, và đây là cách viết bằng class thông thường.

import React, { Component } from 'react'

export default class Counter extends Component {
    constructor(props) {
    super(props)
    //Khởi tạo state
    this.state = {
      count: 0
    }
  }
  
  increment() {
    this.setState({ count: this.state.count + 1 })
  }

  decrement() {
    this.setState({ count: this.state.count - 1 })
  }

  render() {
    return (
      <h1>{this.state.count}</h1>
      <button  onClick={() => this.increment()}>Increment!</button>
      <button  onClick={() => this.decrement()}>Decrement!</button>
    )
  }
}

Nhưng khi chúng ta sử dụng React Hooks (cụ thể ở ví dụ bên dưới là sử dụng hook useState) sẽ nhanh hơn rất nhiều.

import React, { useState } from "react"

export default function Counter() {
  const [count, setCount] = useState(0)

  
   return (
     <h1>{count}</h1>
     <button  onClick={() => setCount(count + 1)}>Increment!</button>
     <button  onClick={() => setCount(count - 1)}>Decrement!</button>
   )
}

Hai cách viết trên đều có một chức năng giống nhau nhưng khi chúng ta sử dụng React Hooks sẽ giúp giảm các đoạn mã và tài nguyên.

2. Các hooks thường dùng trong ReactJS

useState

Việc sử dụng useState() cho phép chúng ta có thể làm việc với state bên trong functional component mà không cần chuyển nó về class component. Ở ví dụ bên trên mình cũng đã sử dụng useState() để cập nhật state.

useEffect

useEffect() là function nắm bắt tất cả các sự thay đổi của code. Nó giúp chúng ta xử lý các side effects, useEffect sẽ tương đương với các hàm componentDidMount, componentDidUpdatecomponentWillUnMount trong LifeCycle. Ví dụ:

import React, { useEffect } from 'react'

export default function Something {
  useEffect(() => {
    fetch(...) //call api
  }, [])
  return (...)
}

Ta có thể thấy, callback trong useEffect hoạt đống giống như ComponentDidMount khi sử dụng class. Để tránh việc hàm useEffect luôn chạy vào mỗi khi có thay đổi State thì ta có thể truyền vào tham số thứ 2 trong useEffect đó là 1 array, trong array này ta có thể truyền vào đó những giá trị mà useEffect sẽ subcribe nó, tức là chỉ khi nào những giá trị đó thay đổi thì hàm useEffect mới được thực thi. Hoặc bạn cũng có thể truyền vào 1 array rỗng thì khi đó nó sẽ chỉ chạy 1 lần đầu tiên sau khi render giống với hàm ComponentDidMount.

useEffect(() => {
  console.log(counter)
}, [counter])

Ngoài ra, useEffect còn có thẻ return một cleanup function tương đương với componentWillUnMount, và đây là một trong những trường hợp sử dụng cleanup function.

useEffect(() => {
  const handler = () => {...}
  window.addEventListener('scroll', handler)

  return () => {
    window.removeEventListener('scroll', handler)
  }
}, [])

useContext

useContext là một hooks trong React Hooks cho phép chúng ta có thể làm việc với React Context trong một functional component, đây là cách khởi tạo một context.

const AppContext = React.createContext({ foo: 'bar' })

và đây là cách lấy giá trị từ context thông qua useContext

const value = useContext(AppContext)

useMemo

useMemo giúp chúng ta hạn chế việc thực hiện những tính toán phức tạp mỗi lần component re-render. Bằng cách truyền dependencies ở đối số thứ 2, chỉ khi giá trị một trong các dependencies thay đổi thì việc tính toán mới thực hiện lại.

import { useMemo } from 'react'

const learningProgress = ({ position, lecturesCount  }) => {
  //Phép tính sẽ luôn được thực thi khi conponent re-render
  const progress = Math.trunc(Number(position) / lecturesCount * 100)

  //Phép tính chỉ thực thi lại khi position hoặc lecturesCount thay đổi
  const progress = useMemo(() => Math.trunc(Number(position) / lecturesCount * 100), [position, lecturesCount])
  return (...)
}

useCallback

Tương tự như useMemo, nhưng useCallback có tác dụng là ngăn chặn việc một hàm bị khởi tạo lại mỗi lần re-render, useCallback sẽ sử dụng cùng với React.memo để tránh việc re-render không cần thiết.

import { useState } from 'react'
import Child from './child' 
const App() {
  const [count, setCount] = useState(0)
  const handleSetValue = (text) => {
    console.log(text)
  }

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <Child handleSetValue={handleSetValue} />
    </div>
  )
}

và đây là child component với React.memo

import { memo, useState } from 'react'

const Child = ({ handleSetValue }) => {
  const [text, setText] = useState('')
  console.log('re-render')
  return (
    <div>
      <input type='text' onChange={(e) => setText(e.target.value)} />
      <button onClick={() => handleSetValue(text)}>Click</button>
    </div>
  )
}

export default memo(Child)

Với React.memo, ta mong muốn khi component App re-render, cụ thể là setCount thì component Child sẽ không re-render. Nhưng không, khi App re-render thì hàm handleSetValue cũng được khởi tạo lại với phạm vi mới, nên Child vẫn sẽ re-render. Cách khắc phục là sử dụng useCallback.

import { useState, useCallback } from 'react'
import Child from './child' 
const App() {
  const [count, setCount] = useState(0)
  const handleSetValue = useCallback((text) => {
    console.log(text)
  }, [])

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <Child handleSetValue={handleSetValue} />
    </div>
  )
}

Và bây giờ các bạn đã có kết quả như mong muốn.

useReducer

useReducer được sử dụng để xử lý các state phức tạp và việc chia sẻ state giữa các component, flow làm việc của useReducer cũng giống với redux.

function reducer(state, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return  state - 1
    default:
      throw new Error()
  }
}

function Counter() {
  const [count, dispatch] = useReducer(reducer, 0)
  return (
    <>
      <h1>{count}</h1>
      <button onClick={() => dispatch({type: 'DECREMENT'})}>Decrement</button>
      <button onClick={() => dispatch({type: 'INCREMENT'})}>Increment</button>
    </>
  )
}

Tạm kết

Đến đây các bạn đã biết được được công dụng và những điểm mạnh tuyệt vời của react hooks đúng không nào <3. Ngoài những hooks mình đã giới thiệu ở trên, còn nhiều hooks khác như: useLayoutEffect, useImperativeHandle,... . Mình sẽ giới thiệu ở những bài viết sau về chi tiết các chức năng của từng hooks. Các bạn cũng có thể tìm hiểu cụ thể hơn tại đây.

0Bình luận

Bài viết liên quan

thumbnail
avatar

Huy Pham

21/03/2022|3 phút đọc

Custom hooks là gì ? Xây dựng hook useWindowSize và useDebounce trong ReactJS.

Khi làm việc với ReactJS chắc hẳn bạn không còn xa lạ với các hooks như useState, useRef, useEffect,… Ngoài các hooks có sẵn, bạn ...

thumbnail
avatar

Huy Pham

22/03/2022|2 phút đọc

Cài đặt Tailwind CSS cho dự án NextJS

Trong bài viết này, chúng ta hãy cùng tìm hiểu cách để sử dụng Tailwind CSS cho dự án NextJS, một sự kết hợp tuyệt vời.

thumbnail
avatar

Huy Pham

23/03/2022|2 phút đọc

Xây dựng một Infinite Scroll Component với React Hooks

khi sử dụng các trang web, đặc biệt là mạng xã hội, có lẽ các bạn đã không ít lần nhìn thấy họ sử dụng kỹ thuật Infinite Scroll (c...

author

Huy Pham

Software Engineer

Insanity is doing the same thing, over and over again, but expecting different results.

Các thẻ đề xuất