Devahoy Logo
PublishedAt

React

[React.js]ใช้ SWR เพื่อดึงข้อมูล API

[React.js]ใช้ SWR เพื่อดึงข้อมูล API

สวัสดีครับ บทความนี้มาแนะนำการเขียน React เพื่อดึงข้อมูลจาก API ด้วยการใช้ SWR นะครับ เนื่องจากผมเคยเขียนบทความไว้เมื่อ 3 ปีที่แล้ว เนื้อหาน่าจะค่อนข้างเก่า และตัว SWR ก็มีการอัพเดทไปพอสมควร เลยเขียนบทความใหม่ดีกว่า

SWR เป็น React Hooks สำหรับ Data Fetching หรือการดึงข้อมูลจาก API ตัว SWR มาจาก stale-while-revalidate เป็น HTTP Caching รูปแบบนึง คือ SWR จะ return ค่าจาก cache (stale) จากนั้น จะส่ง fetch request (revalidate) สุดท้าย ก็ได้ response ที่ข้อมูลอัพเดท

ฉะนั้นสรุปสิ่งที่ SWR ทำคือ

  1. (Stale) ทำการดึง data จาก cache มาให้เราก่อน
  2. (Revalidate) จากนั้นก็ ยิง request ไปที่ API
  3. นำข้อมูลจาก API ที่ได้มาอัพเดทกับข้อมูลเดิม

ถ้าเราลองไปดู Overview จากหน้าเว็บ จะเห็นโค๊ดด้านล่างนี้เลย

1
import useSWR from 'swr'
2
3
function Profile() {
4
const { data, error, isLoading } = useSWR('/api/user', fetcher)
5
6
if (error) return <div>failed to load</div>
7
if (isLoading) return <div>loading...</div>
8
return <div>hello {data.name}!</div>
9
}

จะเห็นว่า เราสามารถเรียกใช้งาน useSWR โดยส่ง url ที่เราต้องการ request ได้เลย และส่วน fetcher ก็คือ function สุดท้าย เราก็จะได้ response เป็น data, error และ isLoading

ถ้าเทียบกับปกติ หลายๆ คนคงใช้ useEffect() เพื่อดึงข้อมูล จากนั้น เมื่อได้ข้อมูล ก็ทำการ setState() เพื่อเอาค่าใน state มาแสดง กำหนด isLoading เอง setError เอง เป็นต้น พอเป็น SWR ก็ง่ายเลย

fetcher

fetcher เป็น async function ที่รับค่า key จาก useSWR และ return data กลับไป

จะเห็นว่า fetcher เป็นแค่ function ฉะนั้น เราสามารถใช้ fetch library อะไรก็ได้ เช่นตัวอย่าง ใช้ fetch

1
const fetcher = (url) => fetch(url).then((r) => r.json())
2
3
function App() {
4
const { data, error } = useSWR('/api/data', fetcher)
5
// ...
6
}

และแบบ axios

1
import axios from 'axios'
2
3
const fetcher = (url) => axios.get(url).then((res) => res.data)
4
5
function App() {
6
const { data, error } = useSWR('/api/data', fetcher)
7
// ...
8
}

Revalidate on Focus

ตัว SWR จะทำการ auto revalidate คือไปโหลดข้อมูลให้เราอัตโนมัติ เมื่อเรา on focus change เช่น สลับหน้าจอ หรือกลับมาจากหน้าอื่น มากดหน้า Tab / Browser เป็นต้น

ซึ่งเราสามารถ Config แบบ Global หรือแบบนี้ก็ได้

1
useSWR(key, fetcher, {
2
revalidateOnFocus: false
3
})

Mutate

การเปลี่ยนแปลงข้อมูล เช่น เรียก mutate() เพื่อให้ SWR ทำการ revalidate ข้อมูลใหม่ มาแสดง

1
import useSWR, { useSWRConfig } from 'swr'
2
3
function App() {
4
const { mutate } = useSWRConfig()
5
6
return (
7
<div>
8
<button
9
onClick={() => {
10
// ทำการ revalidate
11
mutate('/api/user')
12
}}
13
>
14
Logout
15
</button>
16
</div>
17
)
18
}

หรือ เราสามารถอัพเดทข้อมูล ส่งข้อมูลไปที่ Server ในขณะเดียวกัน หน้า UI ผู้ใช้งานก็รู้สึกว่ามัน Realtime ไม่เห็นช่วงรอข้อมูล response จาก Server เพราะอ่านค่าจาก local ก่อน จากนั้นเมื่อได้ response จาก Server ค่อยเอาค่ามา sync กัน (ทั้งหมด SWR จัดการให้หมด)

1
import useSWR from 'swr'
2
3
function Profile() {
4
const { data, mutate } = useSWR('/api/user', fetcher)
5
6
return (
7
<div>
8
<h1>My name is {data.name}.</h1>
9
<button
10
onClick={async () => {
11
const newName = data.name.toUpperCase()
12
// send a request to the API to update the data
13
await requestUpdateUsername(newName)
14
// update the local data immediately and revalidate (refetch)
15
// NOTE: key is not required when using useSWR's mutate as it's pre-bound
16
mutate({ ...data, name: newName })
17
}}
18
>
19
Uppercase my name!
20
</button>
21
</div>
22
)
23
}

อ่านเพิ่มเติม

Happy Coding ❤️

Authors
avatar

Chai Phonbopit

เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust

Related Posts