[React Basics] Tăng tốc ứng dụng React với thư viện Axios: Tại sao nên sử dụng?

Trong thế giới lập trình cùng React, việc giao tiếp với các API để lấy và gửi dữ liệu là một nhiệm vụ cốt lõi. Mặc dù trình duyệt cung cấp fetch API tích hợp sẵn, Axios đã nổi lên như một thư viện của bên thứ ba được ưa chuộng và mạnh mẽ hơn, mang đến một giao diện trực quan, nhiều tính năng và quy trình làm việc hiệu quả hơn.

Tăng tốc ứng dụng React với thư viện Axios: Tại sao nên sử dụng

Bài viết này sẽ giúp bạn khai phá toàn bộ tiềm năng của Axios trong các dự án React của mình, từ những yêu cầu cơ bản đến các kỹ thuật nâng cao.

Tại sao nên chọn Axios thay vì fetch?

Trước khi đi sâu vào kỹ thuật, hãy cùng tìm hiểu lý do tại sao cộng đồng React lại ưu ái Axios đến vậy.

  • Tự động chuyển đổi JSON: Axios tự động chuyển đổi dữ liệu phản hồi thành định dạng JSON, giúp bạn bỏ qua bước response.json() thủ công như khi dùng fetch.
  • Xử lý lỗi tốt hơn: Axios coi các mã trạng thái ngoài phạm vi 2xx (ví dụ: 404, 500) là lỗi và sẽ tự động reject promise. Điều này giúp việc bắt lỗi trong khối catch trở nên tự nhiên và dễ đoán hơn.
  • Interceptors: Đây là một trong những tính năng mạnh mẽ nhất của Axios. Interceptors cho phép bạn chặn và sửa đổi các yêu cầu (requests) trước khi chúng được gửi đi hoặc các phản hồi (responses) trước khi chúng được xử lý. Điều này cực kỳ hữu ích cho việc thiết lập header xác thực, ghi log, hoặc xử lý lỗi toàn cục.
  • Bảo vệ chống lại XSRF: Axios có cơ chế tích hợp để bảo vệ chống lại các cuộc tấn công Cross-Site Request Forgery (XSRF).
  • Hủy bỏ yêu cầu: Axios cung cấp một cách đơn giản để hủy bỏ các yêu cầu đang chờ xử lý, một tính năng quan trọng để tránh các cuộc gọi API không cần thiết và rò rỉ bộ nhớ.
  • Tương thích trình duyệt cũ: Axios sử dụng XMLHttpRequest bên dưới, do đó nó có khả năng tương thích tốt hơn với các trình duyệt cũ hơn so với fetch.

Bắt đầu với Axios trong dự án React

Để bắt đầu, hãy thêm Axios vào dự án của bạn bằng trình quản lý gói yêu thích:

# Sử dụng npm
npm install axios

# Hoặc sử dụng yarn
yarn add axios

Sau khi cài đặt, bạn chỉ cần import nó vào component React nơi bạn muốn thực hiện các cuộc gọi API.

import axios from 'axios'

Thực hiện các thao tác CRUD cơ bản

Giao tiếp với API thường xoay quanh bốn thao tác chính: Create, Read, Update, và Delete, hay còn gọi là CRUD.

1. Lấy dữ liệu (GET Request)

Đây là thao tác phổ biến nhất. Hãy xem một ví dụ về cách lấy danh sách người dùng từ một API giả lập và hiển thị chúng.

import React, { useState, useEffect } from 'react'
import axios from 'axios'

function UserList() {
  const [users, setUsers] = useState([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)

  useEffect(() => {
    const fetchUsers = async () => {
      try {
        const response = await axios.get(
          'https://jsonplaceholder.typicode.com/users',
        )
        setUsers(response.data)
      } catch (err) {
        setError(err.message)
      } finally {
        setLoading(false)
      }
    }

    fetchUsers()
  }, []) // Mảng rỗng đảm bảo useEffect chỉ chạy một lần khi component được mount

  if (loading) return <p>Đang tải...</p>
  if (error) return <p>Lỗi: {error}</p>

  return (
    <div>
      <h1>Danh sách Người dùng</h1>
      <ul>
        {users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  )
}

export default UserList

Điểm chính:

  • Sử dụng async/await cho mã nguồn sạch sẽ, dễ đọc hơn.
  • Dữ liệu trả về từ Axios nằm trong thuộc tính response.data.
  • Khối try...catch...finally giúp quản lý trạng thái tải, dữ liệu và lỗi một cách hiệu quả.

2. Gửi dữ liệu (POST Request)

Để tạo một tài nguyên mới, chúng ta sử dụng phương thức POST, truyền URL làm tham số đầu tiên và đối tượng dữ liệu cần gửi làm tham số thứ hai.

const addUser = async () => {
  try {
    const newUser = { name: 'Gemini AI', email: 'gemini@google.com' }
    const response = await axios.post(
      'https://jsonplaceholder.typicode.com/users',
      newUser,
    )
    console.log('Người dùng mới đã được tạo:', response.data)
    // Cập nhật lại danh sách người dùng
    setUsers([...users, response.data])
  } catch (error) {
    console.error('Lỗi khi thêm người dùng:', error)
  }
}

3. Cập nhật dữ liệu (PUT/PATCH Request)

Tương tự như POST, phương thức PUT được dùng để cập nhật toàn bộ một tài nguyên. Bạn cần cung cấp ID của tài nguyên trong URL.

const updateUser = async (userId) => {
  try {
    const updatedUser = {
      name: 'Gemini AI Updated',
      email: 'gemini.updated@google.com',
    }
    const response = await axios.put(
      `https://jsonplaceholder.typicode.com/users/${userId}`,
      updatedUser,
    )
    console.log('Người dùng đã được cập nhật:', response.data)
  } catch (error) {
    console.error('Lỗi khi cập nhật người dùng:', error)
  }
}

Lưu ý: PATCH cũng được dùng để cập nhật nhưng thường chỉ áp dụng cho một phần của tài nguyên.

4. Xóa dữ liệu (DELETE Request)

Phương thức DELETE khá đơn giản, chỉ cần truyền URL với ID của tài nguyên cần xóa.

const deleteUser = async (userId) => {
  try {
    await axios.delete(`https://jsonplaceholder.typicode.com/users/${userId}`)
    console.log('Người dùng đã được xóa thành công')
    // Lọc người dùng đã xóa ra khỏi state
    setUsers(users.filter((user) => user.id !== userId))
  } catch (error) {
    console.error('Lỗi khi xóa người dùng:', error)
  }
}

Các kỹ thuật nâng cao với Axios

Để tối ưu hóa và làm cho mã nguồn của bạn chuyên nghiệp hơn, hãy tận dụng các tính năng nâng cao của Axios.

1. Tạo một "Instance" Axios

Khi ứng dụng của bạn lớn dần và cần gọi đến cùng một API endpoint với các cấu hình chung (như baseURL, headers), việc tạo một instance là cực kỳ hữu ích. Nó giúp bạn tránh lặp lại mã và quản lý cấu hình tập trung.

Tạo một file riêng, ví dụ api.js:

// src/api.js
import axios from 'axios'

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000, // Yêu cầu sẽ bị hủy sau 10 giây
  headers: {
    'Content-Type': 'application/json',
    // 'Authorization': 'Bearer YOUR_TOKEN' // Có thể thêm token ở đây hoặc dùng interceptor
  },
})

export default apiClient

Bây giờ trong các component, bạn chỉ cần import apiClient thay vì axios.

// Trong component của bạn
import apiClient from '../api'

// ...
const response = await apiClient.get('/products')
// ...

2. Sử dụng Interceptors để quản lý xác thực

Interceptors là công cụ hoàn hảo để tự động đính kèm token xác thực vào mỗi yêu cầu.

Trong file api.js, chúng ta có thể cấu hình interceptor cho request:

// src/api.js
// ... (phần code axios.create)

apiClient.interceptors.request.use(
  (config) => {
    // Lấy token từ localStorage, Redux store, hoặc context
    const token = localStorage.getItem('authToken')
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) => {
    return Promise.reject(error)
  },
)

export default apiClient

Bạn cũng có thể dùng interceptor cho response để xử lý các lỗi toàn cục, chẳng hạn như khi token hết hạn (lỗi 401) và tự động chuyển hướng người dùng về trang đăng nhập.

3. Hủy bỏ yêu cầu (Request Cancellation)

Trong một số trường hợp, như khi người dùng rời khỏi một trang trước khi dữ liệu tải xong, bạn nên hủy yêu cầu đó. Axios sử dụng AbortController (API tiêu chuẩn của trình duyệt) để thực hiện việc này.

import React, { useState, useEffect } from 'react'
import axios from 'axios'

function SearchComponent() {
  const [query, setQuery] = useState('')

  useEffect(() => {
    const controller = new AbortController()

    const searchData = async () => {
      if (query.length < 3) return
      try {
        await axios.get(`/api/search?q=${query}`, {
          signal: controller.signal, // Gắn signal vào yêu cầu
        })
        // Xử lý dữ liệu...
      } catch (error) {
        if (axios.isCancel(error)) {
          console.log('Yêu cầu đã bị hủy:', error.message)
        } else {
          // Xử lý lỗi khác
        }
      }
    }

    searchData()

    // Hàm dọn dẹp sẽ được gọi khi component unmount hoặc query thay đổi
    return () => {
      controller.abort()
    }
  }, [query])

  return (
    <input
      type="text"
      value={query}
      onChange={(e) => setQuery(e.target.value)}
    />
  )
}

4. Tải lên tệp in (File Uploads)

Để tải file lên server, bạn cần sử dụng đối tượng FormData.

const onFileChange = (event) => {
  setSelectedFile(event.target.files[0])
}

const handleFileUpload = async () => {
  const formData = new FormData()
  formData.append('myFile', selectedFile, selectedFile.name)

  try {
    // Đặt header 'Content-Type' là 'multipart/form-data'
    await axios.post('api/uploadfile', formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    })
    console.log('Tải file thành công!')
  } catch (error) {
    console.error('Lỗi khi tải file:', error)
  }
}

Kết luận: Axios chuẩn hóa việc giao tiếp với API

Axios không chỉ là một thư viện để thực hiện các yêu cầu HTTP. Nó là một bộ công cụ mạnh mẽ, linh hoạt và có cấu trúc tốt, giúp đơn giản và chuẩn hóa việc giao tiếp với API trong các ứng dụng React. Bằng cách nắm vững từ các thao tác CRUD cơ bản đến các kỹ thuật nâng cao như tạo instance, sử dụng interceptors và hủy bỏ yêu cầu, bạn có thể xây dựng các ứng dụng React hiệu quả, dễ bảo trì và có khả năng mở rộng cao hơn.

Hãy bắt đầu tích hợp Axios vào dự án tiếp theo của bạn và trải nghiệm sự khác biệt mà nó mang lại!

Bài viết liên quan

[React Basics] Cách deploy ứng dụng React dễ dàng trong 5 phút

Bạn đang gặp khó khăn khi deploy ứng dụng React? Xem ngay hướng dẫn chi tiết từng bước để deploy app React một cách dễ dàng và nhanh chóng.

[React Basics] Hiểu đúng về React.memo: Khi nào dùng và khi nào không?

Đừng quá lạm dụng React.memo! Tìm hiểu cách React.memo hoạt động under the hood và khi nào nên sử dụng để tránh gây hại cho hiệu suất của ứng dụng.

[React Basics] Thuộc tính key trong React: Hiểu rõ và sử dụng hiệu quả

Bạn đã thực sự hiểu về thuộc tính key trong React? Tìm hiểu vai trò, cách dùng hiệu quả và các ví dụ thực tế giúp code của bạn sạch và tối ưu hơn.

[React Basics] Hướng dẫn Testing trong React: Đảm bảo ứng dụng hoạt động hoàn hảo

Tìm hiểu về React testing, unit test và integration test trong bài viết chuyên sâu này. Nâng cao kỹ năng lập trình của bạn bằng cách học cách kiểm thử các React components một cách hiệu quả.