[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 ทำคือ
- (Stale) ทำการดึง data จาก cache มาให้เราก่อน
- (Revalidate) จากนั้นก็ ยิง request ไปที่ API
- นำข้อมูลจาก API ที่ได้มาอัพเดทกับข้อมูลเดิม
ถ้าเราลองไปดู Overview จากหน้าเว็บ จะเห็นโค๊ดด้านล่างนี้เลย
import useSWR from 'swr'
function Profile() {
const { data, error, isLoading } = useSWR('/api/user', fetcher)
if (error) return <div>failed to load</div>
if (isLoading) return <div>loading...</div>
return <div>hello {data.name}!</div>
}
จะเห็นว่า เราสามารถเรียกใช้งาน 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
const fetcher = url => fetch(url).then(r => r.json())
function App () {
const { data, error } = useSWR('/api/data', fetcher)
// ...
}
และแบบ axios
import axios from 'axios'
const fetcher = url => axios.get(url).then(res => res.data)
function App () {
const { data, error } = useSWR('/api/data', fetcher)
// ...
}
Revalidate on Focus
ตัว SWR จะทำการ auto revalidate คือไปโหลดข้อมูลให้เราอัตโนมัติ เมื่อเรา on focus change เช่น สลับหน้าจอ หรือกลับมาจากหน้าอื่น มากดหน้า Tab / Browser เป็นต้น
ซึ่งเราสามารถ Config แบบ Global หรือแบบนี้ก็ได้
useSWR(key, fetcher, {
revalidateOnFocus: false
})
Mutate
การเปลี่ยนแปลงข้อมูล เช่น เรียก mutate()
เพื่อให้ SWR ทำการ revalidate ข้อมูลใหม่ มาแสดง
import useSWR, { useSWRConfig } from 'swr'
function App () {
const { mutate } = useSWRConfig()
return (
<div>
<button onClick={() => {
// ทำการ revalidate
mutate('/api/user')
}}>
Logout
</button>
</div>
)
}
หรือ เราสามารถอัพเดทข้อมูล ส่งข้อมูลไปที่ Server ในขณะเดียวกัน หน้า UI ผู้ใช้งานก็รู้สึกว่ามัน Realtime ไม่เห็นช่วงรอข้อมูล response จาก Server เพราะอ่านค่าจาก local ก่อน จากนั้นเมื่อได้ response จาก Server ค่อยเอาค่ามา sync กัน (ทั้งหมด SWR จัดการให้หมด)
import useSWR from 'swr'
function Profile () {
const { data, mutate } = useSWR('/api/user', fetcher)
return (
<div>
<h1>My name is {data.name}.</h1>
<button onClick={async () => {
const newName = data.name.toUpperCase()
// send a request to the API to update the data
await requestUpdateUsername(newName)
// update the local data immediately and revalidate (refetch)
// NOTE: key is not required when using useSWR's mutate as it's pre-bound
mutate({ ...data, name: newName })
}}>Uppercase my name!</button>
</div>
)
}
อ่านเพิ่มเติม
Happy Coding ❤️
Workshop
รอติดตาม มี 2 ตอนคือ
- [WIP] ดึงข้อมูล Github API ด้วยการใช้ SWR + React + JavaScript
- [WIP] ดึงข้อมูล Github API ด้วยการใช้ SWR + React + TypeScript