+1

React Query - Stack chất lượng với Frontend DEV

image.png Lướt qua 1 số trang tuyển dụng thì mình có đọc được 1 số thông tin tuyển dụng yêu cầu kinh nghiệm về react-query.

Xem thông tin trên npmjs và github thì con số rất ấn tượng với 1,466,787 lượt tải hàng tuần + 41.9k stars vào thời điểm mình viết bài. Vậy hãy cùng tìm hiểu những kiến thức cơ bản về package so hot này nhé. 😘😘

React Query là gì

React-query là 1 thư viện data-fetching dành cho react. Nó có thể fetching, caching, đồng bộ và update data sau khi lấy từ database. Bạn có thể hiểu nó như 1 hệ thống caching mini bên dưới local vậy.

React Query có thể làm gì

Hãy cùng so sánh 1 đoạn code có và không có react-query để thấy được sự khác nhau nhé

Case không sử dụng react-query trong fetching data

Dưới đây là 1 ví dụ về việc fetching data thông thường. Ta sẽ sử dụng useEffect và 3 state nữa để lưu trạng thái của fetch. Bao gồm loading, error, data.

import React, {useState, useEffect} from 'react';
import axios from 'axios';
// regular fetch with axios
function App() {
  const [isLoading, setLoading] = useState(false)
  const [isError, setError] = useState(false)
  const [data, setData] = useState({});
 
  useEffect(() => {
    const fetchData = async () => {
      setError(false);
      setLoading(true);
  
      try {
        const response = await axios('http://swapi.dev/api/people/1/');
  
        setData(response.data);
      } catch (error) {
        setError(true);
      }
      setLoading(false);
    };
    fetchData()
  }, []);
return (
    <div className="App">
      <h1>React Query example with Star Wars API</h1>
      {isError && <div>Something went wrong ...</div>}
 
      {isLoading ? (
        <div>Loading ...</div>
      ) : (
        <pre>{JSON.stringify(data, null, 2)}
        </pre>
      )}
    </div>
  );
}
export default App;

Case sử dụng react-query để fetch data

import React from 'react';
import axios from 'axios';
import {useQuery} from 'react-query';

function App() {
  const { isLoading, error, data } = useQuery('posts', () =>
  axios('http://swapi.dev/api/people/1/'))
return (
    <div className="App">
      <h1>React Query example with star wars API</h1>
      {error && <div>Something went wrong ...</div>}
 
      {isLoading ? (
        <div>Retrieving Luke Skywalker Information ...</div>
      ) : (
        <pre>{JSON.stringify(data, null, 2)}
        </pre>
      )}
    </div>
  );
}
export default App;

Sau khi fetch thì data đã được cache qua key posts. Và ae có thể thấy được react-query hỗ trợ luôn việc xử lý loading, error, data.

Access cache data ở 1 component khác

Rất tiện phải không. Thay vì sử dụng redux hay truyền qua props, ae có thể access luôn data đã cache bằng react-query. Ae để ý tham số posts khi fetch data khi muốn access nó.

import { useQuery } from '@tanstack/react-query';

function CachedPosts() {
  const { data, isLoading, error } = useQuery(['posts']);

  if (isLoading) return <p>Loading cached posts...</p>;
  if (error) return <p>Error loading cached posts.</p>;

  return (
    <div>
      <h2>Cached Posts:</h2>
      {data.map(post => (
        <div key={post.id}>{post.title}</div>
      ))}
    </div>
  );
}

export default CachedPosts;

Add or edit data cache đơn giản và ngắn gọn

import { useQueryClient } from 'react-query';

const Component = () => {
  const queryClient = useQueryClient();

  const addOrUpdateData = () => {
    // Example of updating cache for a query with key 'todos'
    queryClient.setQueryData(['todos'], (oldData) => {
      return [...(oldData || []), { id: 4, title: 'New Todo' }];
    });
  };

  return <button onClick={addOrUpdateData}>Add/Update Todo</button>;
};

useMutation

React query đã thiết kế useQuery để sử dụng fetdata. Và useMutaion để thực điện các action thay đổi data như add, edit, delete. Và đây là 1 ví dụ về 1 case sử dụng.

import { useMutation, useQueryClient } from '@tanstack/react-query';
import axios from 'axios';

const createPost = async (newPost) => {
  const { data } = await axios.post('/api/posts', newPost);
  return data;
};

function CreatePost() {
  const queryClient = useQueryClient();

  const mutation = useMutation(createPost, {
    onMutate: async (newPost) => {
      await queryClient.cancelQueries('posts');
      
      const previousPosts = queryClient.getQueryData('posts');
      queryClient.setQueryData('posts', (old) => [...old, newPost]);

      return { previousPosts };
    },
    
    onError: (err, newPost, context) => {
      queryClient.setQueryData('posts', context.previousPosts);
    },

    onSuccess: () => {
      queryClient.invalidateQueries('posts');
    },

    onSettled: () => {
      queryClient.invalidateQueries('posts');
    },
  });

  const handleCreatePost = () => {
    mutation.mutate({ title: 'New Post', content: 'This is a new post' });
  };

  return (
    <div>
      <button onClick={handleCreatePost} disabled={mutation.isLoading}>
        {mutation.isLoading ? 'Creating Post...' : 'Create Post'}
      </button>
      {mutation.isError && <p>Error creating post.</p>}
      {mutation.isSuccess && <p>Post created successfully!</p>}
    </div>
  );
}

export default CreatePost;
  • queryClient.removeQueries(['todos']); : sử dụng để remove data cache
  • queryClient.invalidateQueries(['todos']);: Như 1 flag để biết rằng data todos này đã cũ. Lần fetch tiếp theo sẽ call lại api
  • queryClient.prefetchQuery(['todos'], fetchTodos); Hoặc bạn cần call luôn api
  • @tanstack/react-query-devtools : là 1 tool để bạn có thể view được data đã cache

Tổng kết:

Ưu điểm:

  • Clearn code, hạn chế phải khai báo nhiều state và thay thể 1 phần code dài dòng của redux
  • Hỗ trợ tốt, tiết kiệm thời gian cho dev về fetch data và tương tác với server data
  • Hữu ích cho các ứng dụng muốn tối ưu mạnh ở client về fetching data và tương tác với server data

Nhược điểm:

  • FE cần quản lý tốt tầng data cache này không thì sẽ là 1 luồng bug mới dành cho tester
  • Việc sử dụng đan xen redux và react-query có thể sẽ gây rối cho luồng code chung

End:

  • Trong 1 môi trường IT đào thải nhanh chóng thì việc update tech là việc hết sức quan trọng. Và React query xứng đáng để bạn tìm hiểu nó
  • Trước khi áp dụng vào dự án ae nên trao đổi kỹ với techlead và member trong team để mn cùng nắm đc nhé
  • Bài viết có gì sai sót mong ae comment cùng thảo luận nhé

All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí