Tuốt tuồn tuột về 4 loại Apollo Client Fetching

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Làm việc với Apollo Client Fetching chắc chắn anh em sẽ gặp 4 từ khoá chính là Queries, Mutation, Subscriptions và Fragment.

Bài viết này mình tham khảo từ trang document của Apollo Client GraphQL, giải thích lại một cách dễ hiểu hơn về các kiểu Fetching. Do tham khảo từ document nên một số nội dung khác ngoài định nghĩa và ví dụ tôi sẽ không đem vào.

Cảm ơn anh em và bắt đầu với Queries thôi.

  Giới thiệu fetch() của javascript
  Hướng dẫn tắt cách tắt Superfetch (SysMain) trên Windows 10

Xem thêm việc làm SSIS hấp dẫn trên TopDev

1. Apollo Client Queries

Queries thì chắc chắn là quá familiar với anh em rồi. Query là để collect data, Apollo Client Queries cũng sinh ra với mục đích tương tự như vậy (Fetch data với useQuery hook).

Tuy nhiên Query này thì khác với Query bên SQL, nên nếu anh em nào beginner với GraphQL chắc ghé đọc qua tí rồi hãy quay lại.

Ví dụ về Queries:

import { gql, useQuery } from '@apollo/client';

const GET_DOGS = gql`
query GetDogs {
dogs {
id
breed
}
}
`;

Phía trên là câu query với GraphQl, query name là GET_DOGS. Primary API mà ta sử dụng là useQuery, argument cho nó là query string. Data trả về từ query sẽ bao gồm 3 thứ.

  • loading
  • error
  • data

Một cái hay của Apollo Client Queries là nó hỗ trợ Caching query result.

Whenever Apollo Client fetches query results from your server, it automatically caches those results locally. This makes subsequent executions of the same query extremely fast.

Khi Apollo Client fetch data từ server, nó sẽ tự động cache lại kết quả ở phía local. Điều này tăng performance do ở những lần query tiếp theo, kết quả sẽ trả về rất nhanh.

Apollo ClientNguồn ảnh: apollographql.com

Cache thì dễ, nhưng lúc update data mới thì sao?. Phải clear hoặc update cache nếu không data trả về sẽ bị sai.

1.1 Các loại Queries Cache

Với câu hỏi này thì Apollo hỗ trợ 2 chiến lược để update lại data:

  • Thứ nhất là Polling
  • Thứ hai là Refetching

Polling thì đúng như cái tên của nó, về cơ bản thì thằng này gần với realtime. Gần thôi nha anh em, vì nó sẽ fetch data theo định kì chứ không phải fetch liên tục.

Polling provides near-real-time synchronization with your server by executing your query periodically at a specified interval.

Polling cung cấp giải pháp gần với realtime data. Cách làm là query theo định kì tới server (theo khoảng thời gian thiết lập cố định)

Ông cố nội Refetching thì khác, ông này cũng update query result, nhưng chỉ lúc nào user có action nào đó. Ví dụ như khi chuyển page sẽ update lại total items chưa xem chẳng hạn.

Refetching enables you to refresh query results in response to a particular user action, as opposed to using a fixed interval.

Refetch chung cho phép “Làm tươi mới” kết quả lấy được từ query dựa trên actions của user. Cái này thì là fixed interval

Thôi viết đến đây, chi tiết cụ thể anh em có thể lên Docs của Apollo đọc ha, ta đi tiếp với Mutation.

2. Apollo Client Mutation

Khác với Queries như ở mục một, nhắc tới query là anh em biết ngay collect data từ backend. Định nghĩa về mutation trong Apollo Client đơn giản hơn nhiều.

2.1 Định nghĩa

Mutations đẻ ra để trả lời cho câu hỏi:

How to modify back-end data?

Làm thế nào để chỉnh sửa data backend?

Câu trả lời thì không thể dễ dàng hơn, mutations. Mutations đẻ ra để thực hiện các methods như REST API ta thường thực hiện (POST, PUT, UPDATE, PATCH, …)

Về mấy cái method này anh em có thể tham khảo bài Http Methods: thất tinh bắc đẩu trận.

Giờ cùng xem thử với Apollo Client Mutation thì làm sao có thể modify data:

import { gql, useMutation } from '@apollo/client';

// Define mutation
const INCREMENT_COUNTER = gql`
# Increments a back-end counter and gets its resulting value
mutation IncrementCounter {
currentValue
}
`;

function MyComponent() {
// Pass mutation to useMutation

const [mutateFunction, { data, loading, error }] = useMutation(INCREMENT_COUNTER);
}

Đầu tiên là khúc import, khúc này cần work với những API nào bên Apollo thì ta cần thảy vào.

The useMutation React hook is the primary API for executing mutations in an Apollo application.

useMutation trong React hook là API chính để thực thi mutations trong ứng dụng Apollo

Apollo Client MutationNguồn ảnh: apollographql.com

Sau khi dã khai báo thì ta cần pass câu query vào useMutation câu query cần thực thi.

const [mutateFunction, { data, loading, error }] = useMutation(INCREMENT_COUNTER);

Tiện lợi không khác gì Queries, nhưng có một điều anh em cần nhớ kĩ:

Unlike useQueryuseMutation doesn’t execute its operation automatically on render. Instead, you call this mutate function.

Không giống như useQuery, useMutation không thực thi một cách tự động khi component khi render. Thay vào đó, ta cần phải gọi mutate function

Cái này thì dễ hiểu, tại vì các actions change tới DB thường mapping tới các actions của user trên FE. Tuy nhiên, với các actions initial khi render, ta cũng thoải mái gọi các function mutation để thực thi.

2.2 Một số thứ khác

Còn data, loading thì tương tự như useQuery, cái này anh em có thể tham khảo ở mục Result bên Apollo Client

function AddTodo() {
let input;

const [addTodo, { data, loading, error }] = useMutation(ADD_TODO);

if (loading) return 'Submitting...';
if (error) return `Submission error! ${error.message}`;

return (

{
e.preventDefault();addTodo({ variables: { text: input.value } });
input.value = ”;
}}
>
{
input = node;
}}
/>
);
}

Ví dụ trên đây thì onSubmit (line 12) sẽ gọi tới mutation function. Apollo Client lúc này sẽ gọi tới Apollo Server để thực thi.

Một số các topics khác liên quan tới Mutation như Providing optionsTracking mutation status và Resetting mutation status thì anh em có thể tham khảo trên trang docs nha. Mình không viết kĩ quá ở đây.

3. Apollo Client Subscriptions

Ngoài queries và mutations, GraphQL cũng support thêm một kiểu tương tác với Apollo Server khác là Subscriptions.

3.1 Định nghĩa

Vậy Subscriptions là gì?

Về mặt bản chất thì Subscriptions cũng giống như Queries, nhưng có một điểm khác biệt chí mạng là chữ “real time”.

Unlike queries, subscriptions are long-lasting operations that can change their result over time. They can maintain an active connection to your GraphQL server (most commonly via WebSocket), enabling the server to push updates to the subscription’s result.

Không giống như queries, subscriptions là một hoạt động lâu dài có thể thay đổi kết quả của chúng trong thời gian thực. Nó cho phép ta duy trì kết nối tới GraphQL Server (thông thường thông qua WebSocket), cho phép máy chủ gửi data mới nhất về kết quả của subscriptions.

Lý thuyết lèo nhèo là thế, về cơ bản ta cứ nhớ Apollo client Subscriptions là real time data. Dựa trên cơ chế của web socket, server có thể liên tục trả về data mới cho client thông qua một connection alive. Tiện lợi mà không cần mò mẫm tới Web Socket.

Subscriptions are useful for notifying your client in real time about changes to back-end data, such as the creation of a new object or updates to an important field.

Subscription rất có lợi khi ta muốn thông báo cho user sự thay đổi data real time. Giống như khởi tạo một object mới hoặc update một field nào đó quan trọng.

3.2 Khi nào nên xài?

Khi nào ta nên sử dụng Subscriptions?

Small, incremental changes to large objects. Repeatedly polling for a large object is expensive, especially when most of the object’s fields rarely change. Instead, you can fetch the object’s initial state with a query, and your server can proactively push updates to individual fields as they occur.

Các đối tượng nhỏ, tăng dần đôi với các đối tượng bự hơn. Lặp đi lặp lại polling cho một object bự thì khá là tốn kém. Đặc biệt là field trong một object rất ít khi thay đổi. Thay vào đó, ta có thể fetch trạng thái ban đầu của một object thông qua query, sau đó server sẽ trả về các update tới các field đo khi có thay đổi.

Má, viết vậy có khi dễ hiểu hơn.

Sau đây là ví dụ cụ thể. Về phía server:

type Subscription {
commentAdded(postID: ID!): Comment
}

Subscriptions là đăng kí, ở phía server khi viết function này đồng nghĩa với việc ta đăng kí bất kì khi nào người dùng có comment mới add vào thì ta sẽ thực hiện một actions gì đó.

Ở phía client thì ta chỉ cần define subscription ta muốn Apollo Client thực thi:

const COMMENTS_SUBSCRIPTION = gql`
subscription OnCommentAdded($postID: ID!) {
commentAdded(postID: $postID) {
id
content
}
}
`;

4. Apollo Client Fragments

Fragments thì hơi confuse, nhưng anh em cứ bám vào title trên document nha.

Share fields between operations

Chia sẻ fields giữa các thao tác

GraphQL fragment is a piece of logic that can be shared between multiple queries and mutations.

GraphQL Fragment là một phần logic cho phép chia sẻ giữa các câu queries và mutations.

fragment NameParts on Person {
firstName
lastName
}

Mỗi thằng Fragment sẽ bao gồm một tập hợp con của các trường thuộc kiểu liên kết của nó. Ví dụ ở trên thì thằng Person sẽ khai báo firstName, và thằng lastName thì thuộc về thằng NameParts.

Lúc này thằng NameParts sẽ trở thành Fragments, ta có thể thêm Fragment vào bất kì cái queries và mutations nào có liên quan tới Person.

query GetPerson {
people(id: "7") {
...NameParts
avatar(size: LARGE)
}
}

Khi thêm NameParts, câu query này tương đương với:

query GetPerson {
people(id: "7") {
firstName
lastName
avatar(size: LARGE)
}
}

Ngon, vậy lúc nào thì ta cần xài tới Fragments. Cái này quan trọng, kinh nghiệm thực tế là nhiều bạn trong teams mình sử dụng Fragments theo kiểu dùng dao mổ trâu đi thịt chim sẻ.

  • Sharing fields between multiple queries, mutations or subscriptions.
  • Breaking your queries up to allow you to co-locate field access with the places they are used.

Đầu tiên là chia sẻ fields giữa các queries, mutations. Thứ hai là bẻ nhỏ queries ra, cho phép xác định chính xác field đó sẽ được sử dụng ở đâu.

Viết mệt vãi nhưng anh em yên tâm. GraphQL sẽ là một topics lớn và có bài ra thường xuyên nha.

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm công việc CNTT hấp dẫn trên TopDev