Devahoy Logo
PublishedAt

React

ดึงข้อมูล Graphql API ด้วย React + urql

ดึงข้อมูล Graphql API ด้วย React + urql

ตัวอย่างการใช้งาน GraphQL บนโปรเจ็ค React.js เพื่อดึงข้อมูล API ผ่าน Graphql โดยตัวอย่างจะใช้ Public API ที่เป็น Country Code Graphql จากเว็บนี้ GraphQL Countries (เนื่องจากเป็นตัวอย่าง สุ่มเอาครับ เพราะบาง api ก็ link เสียหลายตัวเหมือนกัน)

TLDR; วิธีการใช้งาน urql แบบเร็วๆ

  1. ติดตั้ง Dependencies
Terminal window
npm install --save urql graphql
  1. กำหนด Provider และ Client
1
import { createClient, Provider } from 'urql'
2
3
const client = createClient({
4
url: 'https://countries.trevorblades.com/',
5
})
6
7
<Provider value={client}>
8
<App />
9
</Provider>
  1. ใช้งาน Query ใน App.tsx
1
import { useQuery } from 'urql'
2
3
const QueryCountries = ` query {
4
countries {
5
code
6
name
7
}
8
}`
9
10
funciton App() {
11
const [result] = useQuery({
12
query: QueryCountries
13
})
14
15
const { data, fetching, error } = result
16
17
// render data
18
}

Mini Workshop

วันนี้เราจะลองมาทำ Workshop ในการดึงข้อมูลประเทศต่างๆ ผ่าน Graphql API กันนะครับ โดยจะใช้ API ฟรีของเว็บนี้ https://countries.trevorblades.com/ ซึ่ง Concept Graphql เราจะใช้แหล่งอื่นๆ ก็ได้เช่น Pokemon API, Starwars, Github API เป็นต้น เพียงแต่ตัวอย่างเลือกใช้ Countries เพราะว่าเน้นตัวอย่างการใช้งาน นั่นเอง

Step 1 - เริ่มต้นสร้างโปรเจ็ค React

เริ่มต้น ทำการสร้างโปรเจ็ค React ด้วย Vite ขึ้นมา โดยตัวอย่างเป็นแบบ TypeScript

Terminal window
npm create vite@latest hello-graphql -- --template react-ts

Step 2 - ติดตั้ง urql

จากนั้น ผมทำการติดตั้ง urql และ graphql เพื่อจะใช้เป็น Graphql Client

Terminal window
npm install --save urql graphql

Step 3 - สร้าง Client ขึ้นมา

ผมทำการสร้างไฟล์ขึ้นมา ไฟล์นึง ชื่อ graphql-client.ts เอาไว้ที่โฟลเดอร์ src/libs มีข้อมูลแบบนี้ โดยที่มี Query Countries และ Country (แบบ Hardcode TH ไว้อยู่

graphql-client.ts
1
import { createClient } from 'urql'
2
3
export const graphqlClient = createClient({
4
url: 'https://countries.trevorblades.com/'
5
})
6
7
export const QueryCountries = `
8
query {
9
countries {
10
code
11
name
12
}
13
}
14
`
15
16
export const QueryCountry = `
17
query {
18
country(code: "TH") {
19
code
20
name
21
currency
22
capital
23
}
24
}
25
`

เชื่อมต่อกับ Provider ในหน้า main.tsx

main.tsx
1
import { Provider } from 'urql'
2
import { graphqlClient } from './libs/graphql-client'
3
4
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
5
6
{' '}
7
8
<React.StrictMode>
9
<Provider value={graphqlClient}>
10
<App />
11
</Provider>
12
</React.StrictMode>
13
)

Step 4 - ลอง Query Countries

ผมทำการลบไฟล์ App.tsx ออกไปหมด แล้วสร้างใหม่แบบนี้ โดยการให้มันไป Query รายชื่อประเทศทั้งหมด โดยใช้ useQuery

App.tsx
1
import { useQuery } from 'urql'
2
import './App.css'
3
import { QueryCountries } from './libs/graphql-client'
4
5
interface Country {
6
code: string
7
name: string
8
}
9
10
function App() {
11
const [result] = useQuery({
12
query: QueryCountries,
13
})
14
15
const { data, fetching, error } = result
16
17
if (fetching) return <p>Loading...</p>
18
if (error) return <p>{error.message}</p>
19
20
return (
21
<div className="App">
22
<ul>
23
{data?.countries.map((country: Country) => {
24
return (
25
<p>
26
{country.name} ({country.code})
27
</p>
28
)
29
})}
30
</ul>
31
</div>
32
)
33
}
34
35
export default App

จะเห็นว่า เมื่อเราลองดูหน้าเว็บเรา จะมีรายชื่อประเทศ แสดงออกมา แสดงว่าเรา Query ได้แล้ว

Terminal window
npm run dev

Step 5 - เปลี่ยนมา Query ประเทศบ้าง

จากที่เราใช้ QueryCountries เราก็ลองเปลี่ยนเป็น QueryCountry แทน ก็จะได้แบบนี้

1
import { useQuery } from 'urql'
2
import './App.css'
3
import { QueryCountry } from './libs/graphql-client'
4
5
interface Country {
6
code: string
7
name: string
8
}
9
10
function App() {
11
const [result] = useQuery({
12
query: QueryCountry,
13
})
14
15
const { data, fetching, error } = result
16
17
if (fetching) return <p>Loading...</p>
18
if (error) return <p>{error.message}</p>
19
20
return (
21
<div className="App">
22
<p>{data.country.name}
23
</div>
24
)
25
}
26
27
export default App

แต่ข้อมูลของ Country ยังเป็น hard code ที่เรากำหนด TH ไว้ในโค๊ดอยู่เลย (ไว้เปลี่ยน dynamic ในตอนถัดไป)

Step 6 - สร้าง Hook สำหรับ Query

ทำเป็น Hooks ให้มันดีกว่า จะได้แยกข้อมูลได้ชัดเจน โดยผมแบ่งเป็น 2 hooks คือ

  • useCountries - สำหรับ Query รายชื่อประเทศ
  • useCountry - สำหรับ Query ประเทศเดียว มีรายละเอียดที่เราอยากได้

สร้างไฟล์ hooks/useCountires.ts ขึ้นมา แบบนี้

hooks/useCountries.ts
1
import { useQuery } from 'urql'
2
import { QueryCountries } from '../libs/graphql-client'
3
4
const useCountires = () => {
5
const [result] = useQuery({
6
query: QueryCountries
7
})
8
9
return result
10
}
11
12
export default useCountires

และก็ไฟล์ hooks/useCountry.ts

hooks/useCountry.ts
1
import { useQuery } from 'urql'
2
import { QueryCountry } from '../libs/graphql-client'
3
4
const useCountry = () => {
5
const [result] = useQuery({
6
query: QueryCountry
7
})
8
9
return result
10
}
11
12
export default useCountry

ทีนี้ หน้า App.tsx เราอยากจะ query รายชื่อประเทศ หรือ แค่ประเทศเดียว เราก็ใช้ hooks แทน แบบนี้

App.tsx
1
import { useQuery } from 'urql'
2
import './App.css'
3
import { QueryCountries, QueryCountry } from './libs/graphql-client'
4
5
interface Country {
6
code: string
7
name: string
8
}
9
10
function App() {
11
const { data, fetching, error } = useCountries()
12
13
if (fetching) return <p>Loading...</p>
14
if (error) return <p>{error.message}</p>
15
16
return (
17
<div className="App">
18
<ul>
19
{data?.countries.map((country: Country) => {
20
return (
21
<p key={country.code}>
22
{country.name} ({country.code})
23
</p>
24
)
25
})}
26
</ul>
27
</div>
28
)
29
}
30
31
export default App

Step 7 - urql variables

ตัว urql เราสามารถส่ง varaibles ไป Query ได้ ซึ่งเราก็ส่งผ่าน useQuery สิ่งที่เราจะทำคือ เราจะแก้ไข QueryCountry ในไฟล์ graphql-client.ts ให้รับ variable ชื่อ $code ที่นี้ตัว query เราก็จะไม่ใช้ hard code TH แล้ว แต่จะเป็นค่าที่เราส่งมา ผ่าน useQuery

1
export const QueryCountry = `
2
query($code: ID!) {
3
country(code: $code) {
4
code
5
name
6
currency
7
capital
8
emoji
9
}
10
}
11
`

ตรงส่วน useCountry.ts ก็เปลี่ยนให้ส่ง variables และรับค่า Props มาด้วย แบบนี้

1
import { useQuery } from 'urql'
2
import { QueryCountry } from '../libs/graphql-client'
3
4
const useCountry = (code: String) => {
5
const [result] = useQuery({
6
query: QueryCountry,
7
variables: { code }
8
})
9
10
return result
11
}
12
13
export default useCountry

แค่นี้ เวลาเราจะเรียก query เราก็ใช้ useCountry('TH') , useCountry('CN') อะไรก็ว่าไป

Step 8 - Dynamic Country

ขั้นตอนนี้เราจะใช้ state เข้ามาช่วยในการเก็บ country code ที่เราเลือก เมื่อเลือกแล้ว มันก็จะไป Query Country มาแสดงนั่นเอง

1
// 1. default state เป็น TH
2
const [code, setCode] = useState < string > 'TH'
3
4
// 2. เวลาเรียก `useCountry()` ก็ส่ง code ไป
5
const [reuslt] = useCountry(code)

ทีนี้ เราจะ setCode ได้ยังไง? ก็คือ set จาก onClick นั่นเอง ผมแก้ App.tsx ให้มัน render เป็น <button> แทน แบบนี้ เมื่อ click ก็ setCode จากนั้น ก็แสดงผล Country

1
import { useState } from 'react'
2
import './App.css'
3
import useCountires from './hooks/useCountries'
4
import useCountry from './hooks/useCountry'
5
6
interface Country {
7
code: string
8
name: string
9
}
10
11
function App() {
12
const [code, setCode] = useState<string>('TH')
13
14
const { data, fetching, error } = useCountires()
15
const { data: countryData, fetching: countryFetching } = useCountry(code)
16
17
if (fetching) return <p>Loading...</p>
18
if (error) return <p>{error.message}</p>
19
20
return (
21
<div className="App">
22
<h1>React.js + Graphql Example</h1>
23
{countryFetching ? (
24
<p>Loading...</p>
25
) : (
26
<div className="card">
27
<p>
28
{countryData.country.name} {countryData.country.emoji} ({countryData.country.code})
29
</p>
30
<p>Capital: {countryData.country.capital}</p>
31
<p>Currency : {countryData.country.currency}</p>
32
</div>
33
)}
34
35
<ul>
36
{data?.countries.map((country: Country) => {
37
return (
38
<button key={country.code} onClick={() => setCode(country.code)}>
39
{country.name}
40
</button>
41
)
42
})}
43
</ul>
44
</div>
45
)
46
}
47
48
export default App

สุดท้าย ก็จะได้หน้าตาเว็บประมาณนี้ สามารถกด แต่ละประเทศ เพื่อแสดงข้อมูลได้

สรุป

หวังว่า Tutorial นี้จะทำให้ผู้อ่าน / ผู้เรียน ได้เห็นภาพ และสามารถทำ React + Graphql ไปประยุกต์ใช้ในงานอื่นๆ ได้นะครับ ตัวอย่างนี้ก็เป็นเพียงแค่พื้นฐานเท่านั้น สิ่งสำคัญคือ ไปลองฝึกทำดูนะครับ

Happy Coding ❤️

Authors
avatar

Chai Phonbopit

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

Related Posts