บทนำสู่ SWR: React Hooks สำหรับการดึงข้อมูลระยะไกล

เผยแพร่แล้ว: 2022-03-10
สรุปอย่างย่อ ↬ ในบทความนี้ เราจะมาดูวิธีใหม่ในการดึงข้อมูลในแอป React ชื่อ SWR นี่คือชุดของ hooks สำหรับการดึงข้อมูลระยะไกลที่ทำให้สิ่งต่างๆ ง่ายขึ้น เช่น การแคช การแบ่งหน้า และอื่นๆ เราจะสร้างแอป Pokedex ตั้งแต่เริ่มต้นและใช้คุณสมบัติ SWR เพื่อรับข้อมูลและแบ่งหน้า

SWR เป็นไลบรารีน้ำหนักเบาที่สร้างโดย Vercel (เดิมคือ ZEIT) ที่อนุญาตให้ดึงข้อมูล แคช หรือดึงข้อมูลแบบเรียลไทม์โดยใช้ React Hooks สร้างขึ้นด้วย React Suspense ซึ่งช่วยให้คอมโพเนนต์ของคุณ "รอ" สำหรับบางสิ่งก่อนที่จะแสดงผล ซึ่งรวมถึงข้อมูลด้วย SWR ยังมาพร้อมกับคุณสมบัติที่ยอดเยี่ยม เช่น การดึงข้อมูลโดยขึ้นกับ เน้นที่การตรวจสอบซ้ำ การกู้คืนตำแหน่งการเลื่อน และอื่นๆ นอกจากนี้ยังเป็นเครื่องมือที่ทรงพลังมากเนื่องจากเป็นแบ็กเอนด์ไม่เชื่อเรื่องพระเจ้าและรองรับ TypeScript ได้ดี เป็นแพ็คเกจที่มีอนาคตที่สดใส

ทำไมคุณควรดูแล? คุณควรสนใจว่าคุณกำลังมองหาไลบรารี่ที่ไม่เพียงแต่ดึงข้อมูลจาก API แต่ยังทำให้สามารถทำสิ่งต่างๆ เช่น การแคชและการดึงข้อมูลแบบพึ่งพาได้ สิ่งที่จะกล่าวถึงในบทช่วยสอนนี้จะมีประโยชน์เมื่อสร้างแอปพลิเคชัน React ที่มีชิ้นส่วนเคลื่อนไหวจำนวนมาก เป็นที่คาดว่าคุณควรใช้ประโยชน์จาก Axios และ Fetch API แม้ว่าเราจะเปรียบเทียบว่าต่างจาก SWR อย่างไร เราจะไม่ลงรายละเอียดเกี่ยวกับวิธีการใช้งาน

ในคู่มือนี้ ฉันจะแนะนำให้คุณรู้จักกับ React Hooks สำหรับการดึงข้อมูลระยะไกลโดยการสร้างแอป Pokedex ที่ขอข้อมูลจาก Pokemon API เราจะเจาะลึกคุณสมบัติอื่นๆ ที่มาพร้อมกับ SWR ด้วยเช่นกัน และเน้นถึงความแตกต่างเมื่อเปรียบเทียบกับโซลูชันยอดนิยม เช่น Fetch API และไลบรารี Axios และให้เหตุผลว่าทำไมคุณจึงใช้ไลบรารีนี้ และเหตุใดคุณจึงควรจับตาดู SWR

เรามาเริ่มด้วยการตอบคำถามพื้นฐานกันก่อนว่า SWR คืออะไร?

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

SWR คืออะไร?

SWR เป็นอักษรย่อของ stale-while-revalidate เป็นไลบรารี React Hooks สำหรับการดึงข้อมูลระยะไกล SWR ทำงานกับสามขั้นตอนหลัก: ขั้นแรกจะส่งคืนข้อมูลจากแคช (ส่วนที่เก่า) จากนั้นส่งคำขอดึงข้อมูล (ส่วนตรวจสอบซ้ำ) และในที่สุดก็มาพร้อมกับข้อมูลล่าสุด แต่ไม่ต้องกังวล SWR จะจัดการขั้นตอนเหล่านี้ทั้งหมดให้เราเอง สิ่งเดียวที่เราต้องทำคือให้ useSWR ขอพารามิเตอร์ที่จำเป็นเพื่อส่งคำขอ

SWR ยังมีคุณสมบัติที่ดีบางอย่างเช่น:

  • แบ็กเอนด์ไม่เชื่อเรื่องพระเจ้า
  • การนำทางหน้าอย่างรวดเร็ว
  • การตรวจสอบความถูกต้องอีกครั้งในโฟกัส
  • การสำรวจตามช่วงเวลา
  • ขอขจัดความซ้ำซ้อน
  • การกลายพันธุ์ในพื้นที่
  • การแบ่งหน้า
  • TypeScript พร้อมแล้ว
  • รองรับ SSR
  • โหมดใจจดใจจ่อ
  • ตอบสนอง Native support
  • น้ำหนักเบา

ฟังดูวิเศษ? SWR ช่วยลดความซับซ้อนของสิ่งต่าง ๆ และเพิ่มประสบการณ์ผู้ใช้แอพ React ของคุณอย่างแน่นอน และเมื่อเราเริ่มใช้งานในโครงการของเรา คุณจะเห็นว่าทำไมเบ็ดนี้ถึงสะดวก

สิ่งสำคัญคือต้องรู้ว่าชื่อของแพ็คเกจคือ swr หรือ SWR และ hook ที่ใช้เพื่อรับคุณสมบัติ SWR มีชื่อว่า useSWR

ตามทฤษฎีแล้ว SWR อาจเป็นสิ่งที่คุณต้องการเพื่อปรับปรุงการดึงข้อมูลของคุณ อย่างไรก็ตาม เรามีสองวิธีที่ยอดเยี่ยมในการสร้างคำขอ HTTP ในแอปของเรา นั่นคือ Fetch API และไลบรารี Axios

เหตุใดจึงใช้ไลบรารีใหม่เพื่อดึงข้อมูล มาลองตอบคำถามที่ถูกต้องในหัวข้อถัดไป

เปรียบเทียบกับการดึงข้อมูลและ Axios

เรามีหลายวิธีในการสร้างคำขอ HTTP ในแอพ React ของเราแล้ว และสองวิธีที่ได้รับความนิยมมากที่สุดคือ Fetch API และไลบรารี Axios ทั้งคู่ยอดเยี่ยมและช่วยให้เราสามารถดึงหรือส่งข้อมูลได้อย่างง่ายดาย อย่างไรก็ตาม เมื่อดำเนินการเสร็จสิ้น การดำเนินการดังกล่าวจะไม่ช่วยให้เราแคชหรือแบ่งหน้าข้อมูล คุณต้องดำเนินการเอง

Axios หรือ Fetch จะจัดการคำขอและส่งคืนการตอบกลับที่คาดไว้ ไม่มีอะไรมากไปกว่านี้

และเมื่อเทียบกับ SWR จะแตกต่างออกไปเล็กน้อยเนื่องจาก SWR ภายใต้ประทุนใช้ Fetch API เพื่อขอข้อมูลจากเซิร์ฟเวอร์ ซึ่งเป็นประเภทของเลเยอร์ที่สร้างขึ้นบนนั้น อย่างไรก็ตาม มันมีคุณสมบัติที่ดีบางอย่าง เช่น การแคช การแบ่งหน้า การกู้คืนตำแหน่งการเลื่อน การดึงข้อมูลขึ้นอยู่กับ ฯลฯ และเพื่อให้แม่นยำระดับของการเกิดปฏิกิริยาที่ Axios หรือการดึงข้อมูลไม่มี เป็นข้อได้เปรียบอย่างมากเนื่องจากการมีคุณสมบัติดังกล่าวช่วยให้แอป React ของเรารวดเร็วและใช้งานง่าย และลดขนาดโค้ดของเราลงอย่างเห็นได้ชัด

และเพื่อสรุป พึงระลึกไว้เสมอว่า SWR ไม่เหมือนกับ Axios หรือการดึงข้อมูล แม้ว่าจะช่วยในการจัดการกับคำขอ HTTP ก็ตาม SWR นั้นล้ำหน้ากว่าพวกมัน มันมีการปรับปรุงบางอย่างเพื่อให้แอพของเราซิงโครไนซ์กับแบ็กเอนด์และด้วยเหตุนี้จึงเพิ่มประสิทธิภาพของแอพของเรา

ตอนนี้เรารู้แล้วว่า SWR มีความแตกต่างกันอย่างไรเมื่อเปรียบเทียบกับไลบรารี Axios หรือ Fetch API ถึงเวลาที่จะลงลึกถึงเหตุผลที่ใช้เครื่องมือดังกล่าว

การอ่านที่แนะนำ : การ ใช้ REST API ในการตอบสนองด้วยการดึงข้อมูลและ Axios

เหตุใดจึงต้องใช้ SWR สำหรับการดึงข้อมูล

ดังที่ฉันได้กล่าวไว้ก่อนหน้านี้ SWR มาพร้อมกับคุณสมบัติที่มีประโยชน์ซึ่งช่วยเพิ่มความสามารถในการใช้งานแอพของคุณได้อย่างง่ายดาย ด้วย SWR คุณสามารถแบ่งหน้าข้อมูลของคุณในเวลาไม่นานโดยใช้ useSWRPages คุณยังสามารถดึงข้อมูลที่ขึ้นอยู่กับคำขออื่นหรือกู้คืนตำแหน่งการเลื่อนเมื่อคุณกลับไปที่หน้าที่กำหนด และอื่นๆ อีกมากมาย

โดยปกติ เราจะแสดงข้อความโหลดหรือสปินเนอร์ให้ผู้ใช้เห็นขณะดึงข้อมูลจากเซิร์ฟเวอร์ และด้วย SWR คุณสามารถทำให้ดีขึ้นได้ด้วยการแสดงข้อมูลแคชหรือข้อมูลเก่าแก่ผู้ใช้ในขณะที่ดึงข้อมูลใหม่จาก API และเมื่อดำเนินการเสร็จสิ้น ระบบจะตรวจสอบข้อมูลอีกครั้งเพื่อแสดงเวอร์ชันใหม่ และคุณไม่จำเป็นต้องดำเนินการใดๆ SWR จะแคชข้อมูลในครั้งแรกที่คุณดึงข้อมูลและดึงข้อมูลโดยอัตโนมัติเมื่อมีการส่งคำขอใหม่

จนถึงตอนนี้ เราเห็นแล้วว่าเหตุใดการใช้ SWR บน Axios หรือการดึงข้อมูลจึงดีกว่า ขึ้นอยู่กับสิ่งที่คุณตั้งเป้าที่จะสร้าง แต่ในหลายกรณี ฉันจะแนะนำให้ใช้ SWR เพราะมันมีคุณสมบัติที่ยอดเยี่ยมที่นอกเหนือไปจากการดึงและส่งคืนข้อมูล

ที่กล่าวว่าตอนนี้เราสามารถเริ่มสร้างแอป React และใช้ไลบรารี SWR เพื่อดึงข้อมูลระยะไกลได้

มาเริ่มด้วยการตั้งโครงการใหม่กัน

การตั้งค่า

ดังที่ฉันได้กล่าวไว้ก่อนหน้านี้ในบทนำ เราจะสร้างแอปที่ดึงข้อมูลจาก Pokemon API คุณสามารถใช้ API อื่นได้หากต้องการ ฉันจะใช้ตอนนี้

และในการสร้างแอพใหม่ เราต้องรันคำสั่งต่อไปนี้บนเทอร์มินัล:

 npx create-react-app react-swr

ต่อไป เราต้องติดตั้งไลบรารี SWR โดยไปที่โฟลเดอร์ที่มีแอป React ก่อน

 cd react-swr

และรันบนเทอร์มินัลด้วยคำสั่งต่อไปนี้เพื่อติดตั้งแพ็คเกจ SWR

 yarn add swr

หรือถ้าคุณใช้ npm:

 npm install swr

ตอนนี้เราตั้งค่าเสร็จแล้ว มาจัดโครงสร้างโครงการดังต่อไปนี้เพื่อเริ่มใช้ SWR:

 src ├── components | └── Pokemon.js ├── App.js ├── App.test.js ├── index.js ├── serviceWorker.js ├── setupTests.js ├── package.json ├── README.md ├── yarn-error.log └── yarn.lock

อย่างที่คุณเห็น โครงสร้างโฟลเดอร์นั้นเรียบง่าย สิ่งเดียวที่ควรสังเกตคือโฟลเดอร์ components ที่เก็บไฟล์ Pokemon.js จะใช้ในภายหลังเป็นองค์ประกอบการนำเสนอเพื่อแสดงโปเกมอนตัวเดียวเมื่อเราได้รับข้อมูลจาก API

ยอดเยี่ยม! ด้วยวิธีนี้ เราสามารถเริ่มดึงข้อมูลจาก API โดยใช้ useSWR

กำลังดึงข้อมูลระยะไกล

แพ็คเกจ SWR มีคุณสมบัติที่มีประโยชน์บางอย่างดังที่เราได้เห็นข้างต้น อย่างไรก็ตาม มีสองวิธีในการกำหนดค่าไลบรารีนี้: ในเครื่องหรือทั่วโลก

การตั้งค่าในเครื่องหมายความว่าทุกครั้งที่เราสร้างไฟล์ใหม่ เราต้องตั้งค่า SWR อีกครั้งเพื่อให้สามารถดึงข้อมูลระยะไกลได้ และการตั้งค่าส่วนกลางช่วยให้เรานำส่วนหนึ่งของการกำหนดค่ากลับมาใช้ใหม่ภายในไฟล์ต่างๆ ได้ เนื่องจากฟังก์ชัน fetcher สามารถประกาศเพียงครั้งเดียวและใช้ได้ทุกที่

และไม่ต้องกังวล เราจะเห็นทั้งสองอย่างในบทความนี้ แต่สำหรับตอนนี้ มาเริ่มกันเลยดีกว่าและเพิ่มโค้ดที่มีความหมายในไฟล์ App.js

การแสดงข้อมูล

 import React from 'react' import useSWR from 'swr' import { Pokemon } from './components/Pokemon' const url = 'https://pokeapi.co/api/v2/pokemon' const fetcher = (...args) => fetch(...args).then((res) => res.json()) function App() { const { data: result, error } = useSWR(url, fetcher) if (error) return <h1>Something went wrong!</h1> if (!result) return <h1>Loading...</h1> return ( <main className='App'> <h1>Pokedex</h1> <div> {result.results.map((pokemon) => ( <Pokemon key={pokemon.name} pokemon={pokemon} /> ))} </div> </main> ) } export default App

อย่างที่คุณเห็น เราเริ่มต้นด้วยการนำเข้า useSWR จากไลบรารี SWR นี่เป็นการประกาศ URL ของ API ที่คุณต้องการรับข้อมูล และฟังก์ชันในการดึงข้อมูลเหล่านี้

ฟังก์ชัน fetcher ใช้สำหรับแปลงข้อมูลเป็น JSON รับข้อมูลที่ดึงออกมาเป็นอาร์กิวเมนต์และส่งคืนบางสิ่ง

โปรดสังเกตว่าที่นี่ ฉันใช้โอเปอเรเตอร์ Rest ( (...args) ) เนื่องจากฉันไม่แน่ใจเกี่ยวกับประเภทและความยาวของข้อมูลที่ได้รับเป็นพารามิเตอร์ ดังนั้น ฉันจึงคัดลอกทุกอย่างก่อนที่จะส่งผ่านอีกครั้งเพื่อเป็นอาร์กิวเมนต์ในการ fetch เมธอดที่จัดเตรียมโดย useSWR ซึ่งแปลงข้อมูลเป็น JSON และส่งคืน

ที่กล่าวว่าขณะนี้ fetcher และ url ของ API สามารถส่งผ่านเป็นพารามิเตอร์ไปยัง useSWR hook ได้ ด้วยเหตุนี้ จึงสามารถร้องขอและส่งคืนสถานะสองสถานะ: ข้อมูลที่ดึงมาและสถานะข้อผิดพลาด และ data: result เหมือนกับ data.result เราใช้ object destructuring เพื่อดึง result จาก data

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

ตอนนี้เรามีข้อมูลแล้วและส่งต่อไปยังส่วนประกอบโปเกมอน ถึงเวลาอัปเดต Pokemon.js เพื่อให้สามารถรับและแสดงข้อมูลได้

การสร้างส่วนประกอบโปเกมอน

 import React from 'react' import useSWR from 'swr' const fetcher = (...args) => fetch(...args).then((res) => res.json()) export const Pokemon = ({ pokemon }) => { const { name } = pokemon const url = 'https://pokeapi.co/api/v2/pokemon/' + name const { data, error } = useSWR(url, fetcher) if (error) return <h1>Something went wrong!</h1> if (!data) return <h1>Loading...</h1> return ( <div className='Card'> <span className='Card--id'>#{data.id}</span> <img className='Card--image' src={data.sprites.front_default} alt={name} /> <h1 className='Card--name'>{name}</h1> <span className='Card--details'> {data.types.map((poke) => poke.type.name).join(', ')} </span> </div> ) }

ที่นี่ เรามีองค์ประกอบที่ได้รับข้อมูลโปเกมอนเพียงรายการเดียวจาก API และแสดงข้อมูลนั้น อย่างไรก็ตาม ข้อมูลที่ได้รับมีไม่ครบทุกช่องที่จำเป็น ดังนั้นเราจึงต้องส่งคำขออีกครั้งไปยัง API เพื่อรับวัตถุ Pokemon ที่สมบูรณ์

และอย่างที่คุณเห็น เราใช้กระบวนการเดียวกันในการดึงข้อมูล แม้ว่าครั้งนี้เราจะเพิ่มชื่อของโปเกมอนต่อท้าย URL ก็ตาม

อย่างไรก็ตาม หากคุณไม่คุ้นเคยกับการทำลายโครงสร้าง ({ pokemon }) จะเหมือนกับการรับอุปกรณ์ประกอบฉากและการเข้าถึงวัตถุโปเกมอนด้วย props.pokemon เป็นเพียงการจดชวเลขเพื่อดึงค่าออกจากวัตถุหรืออาร์เรย์

ด้วยสิ่งนี้ หากคุณไปที่โฟลเดอร์รูทของโปรเจ็กต์และรันบนเทอร์มินัล คำสั่งต่อไปนี้:

 yarn start

หรือถ้าคุณใช้ npm:

 npm start

คุณควรเห็นว่ามีการดึงข้อมูลจาก Pokemon API สำเร็จและแสดงตามที่คาดไว้

กำลังเรียก
กำลังดึงภาพประกอบ (ตัวอย่างขนาดใหญ่)

ยอดเยี่ยม! ขณะนี้ เราสามารถดึงข้อมูลระยะไกลด้วย SWR ได้แล้ว อย่างไรก็ตาม การตั้งค่านี้เป็นแบบโลคัลและอาจซ้ำซ้อนเล็กน้อย เพราะคุณจะเห็นแล้วว่า App.js และ Pokemon.js ใช้ฟังก์ชันดึงข้อมูลเดียวกันเพื่อทำสิ่งเดียวกัน

แต่โชคดีที่แพ็คเกจนี้มาพร้อมกับผู้ให้บริการที่สะดวกชื่อ SWRConfig ที่ช่วยกำหนดค่า SWR ทั่วโลก เป็นคอมโพเนนต์ของ wrapper ที่อนุญาตให้คอมโพเนนต์ย่อยใช้การกำหนดค่าส่วนกลางและฟังก์ชัน fetcher

ในการตั้งค่า SWR ทั่วโลก เราต้องอัปเดตไฟล์ index.js เนื่องจากเป็นตำแหน่งที่องค์ประกอบแอปแสดงผลโดยใช้ React DOM หากต้องการ คุณสามารถใช้ SWRConfig ได้โดยตรงในไฟล์ App.js

การกำหนดค่า SWR ทั่วโลก

 import React from 'react' import ReactDOM from 'react-dom' import { SWRConfig } from 'swr' import App from './App' import './index.css' const fetcher = (...args) => fetch(...args).then((res) => res.json()) ReactDOM.render( <React.StrictMode> <SWRConfig value={{ fetcher }}> <App /> </SWRConfig> </React.StrictMode>, document.getElementById('root') )

อย่างที่คุณเห็น เราเริ่มต้นด้วยการนำเข้า SWRConfig ซึ่งเป็นผู้ให้บริการที่ต้องการห่อส่วนประกอบที่สูงกว่าหรือเพียงส่วนหนึ่งของแอป React ของคุณที่ต้องใช้คุณสมบัติ SWR ใช้เป็นค่าอุปกรณ์ประกอบฉากที่คาดหวังวัตถุของการกำหนดค่า คุณสามารถส่งผ่านคุณสมบัติมากกว่าหนึ่งรายการไปยังวัตถุ config ที่นี่ ฉันแค่ต้องการฟังก์ชันเพื่อดึงข้อมูล

ตอนนี้ แทนที่จะประกาศฟังก์ชัน fetcher ในทุกไฟล์ เราสร้างมันที่นี่และส่งผ่านเป็นค่าไปยัง SWRConfig ด้วยเหตุนี้ เราจึงสามารถดึงข้อมูลได้ทุกระดับในแอปของเราโดยไม่ต้องสร้างฟังก์ชันอื่น และด้วยเหตุนี้จึงหลีกเลี่ยงความซ้ำซ้อน

นอกจากนั้น fetcher เท่ากับ fetcher: fetcher มันเป็นเพียงน้ำตาลประโยคที่เสนอโดย ES6 ด้วยการเปลี่ยนแปลงนั้น เราต้องอัปเดตส่วนประกอบของเราเพื่อใช้การกำหนดค่าส่วนกลาง

การใช้ Global SWR Config

 import React from 'react' import useSWR from 'swr' import { Pokemon } from './components/Pokemon' const url = 'https://pokeapi.co/api/v2/pokemon' function App() { const { data: result, error } = useSWR(url) if (error) return <h1>Something went wrong!</h1> if (!result) return <h1>Loading...</h1> return ( <main className='App'> <h1>Pokedex</h1> <div> {result.results.map((pokemon) => ( <Pokemon key={pokemon.name} pokemon={pokemon} /> ))} </div> </main> ) } export default App

ตอนนี้ เราต้องส่ง url ไป useSWR เท่านั้น แทนที่จะส่งเมธอด url และ fetcher มาปรับแต่งองค์ประกอบโปเกมอนกันสักหน่อย

 import React from 'react' import useSWR from 'swr' export const Pokemon = ({ pokemon }) => { const { name } = pokemon const url = 'https://pokeapi.co/api/v2/pokemon/' + name const { data, error } = useSWR(url) if (error) return <h1>Something went wrong!</h1> if (!data) return <h1>Loading...</h1> return ( <div className='Card'> <span className='Card--id'>#{data.id}</span> <img className='Card--image' src={data.sprites.front_default} alt={name} /> <h1 className='Card--name'>{name}</h1> <span className='Card--details'> {data.types.map((poke) => poke.type.name).join(', ')} </span> </div> ) }

คุณจะเห็นว่าเราไม่มีฟังก์ชัน fetcher อีกต่อไปแล้ว ด้วยการกำหนดค่าส่วนกลางซึ่งส่งผ่านฟังก์ชันไปยัง useSWR ภายใต้ประทุน

ตอนนี้คุณสามารถใช้ฟังก์ชัน global fetcher ได้ทุกที่ในแอปของคุณ สิ่งเดียวที่ขอ useSWR ต้องการดึงข้อมูลระยะไกลคือ URL

อย่างไรก็ตาม เรายังคงสามารถปรับปรุงการตั้งค่าเพิ่มเติมได้โดยการสร้าง hook ที่กำหนดเองเพื่อหลีกเลี่ยงการประกาศ URL ซ้ำแล้วซ้ำเล่า เพียงแต่ส่งผ่านเป็นพารามิเตอร์ของเส้นทางแทน

การตั้งค่าขั้นสูงโดยการสร้าง Hook แบบกำหนดเอง

ในการทำเช่นนั้น คุณต้องสร้างไฟล์ใหม่ในรูทของโปรเจ็กต์ชื่อ useRequest.js (คุณสามารถตั้งชื่อไฟล์อะไรก็ได้ตามต้องการ) และเพิ่มบล็อคโค้ดด้านล่างนี้ลงไป

 import useSwr from 'swr' const baseUrl = 'https://pokeapi.co/api/v2' export const useRequest = (path, name) => { if (!path) { throw new Error('Path is required') } const url = name ? baseUrl + path + '/' + name : baseUrl + path const { data, error } = useSwr(url) return { data, error } }

ในที่นี้ เรามีฟังก์ชันที่รับพาธและเลือกชื่อและผนวกเข้ากับ URL ฐานเพื่อสร้าง URL ที่สมบูรณ์ จากนั้นจะตรวจสอบว่าได้รับพารามิเตอร์ชื่อหรือไม่และจัดการตามนั้น

จากนั้น URL นั้นจะถูกส่งผ่านเป็นพารามิเตอร์ไปยังฮุ useSWR เพื่อให้สามารถดึงข้อมูลระยะไกลและส่งคืนได้ และถ้าไม่ผ่านเส้นทางจะเกิดข้อผิดพลาด

ยอดเยี่ยม! ตอนนี้เราต้องปรับแต่งส่วนประกอบเล็กน้อยเพื่อใช้ hook ที่กำหนดเองของเรา

 import React from 'react' import { useRequest } from './useRequest' import './styles.css' import { Pokemon } from './components/Pokemon' function App() { const { data: result, error } = useRequest('/pokemon') if (error) return <h1>Something went wrong!</h1> if (!result) return <h1>Loading...</h1> return ( <main className='App'> <h1>Pokedex</h1> <div> {result.results.map((pokemon) => ( <Pokemon key={pokemon.name} pokemon={pokemon} /> ))} </div> </main> ) } export default App

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

มาอัพเดทองค์ประกอบโปเกมอนกัน

 import React from 'react' import { useRequest } from '../useRequest' export const Pokemon = ({ pokemon }) => { const { name } = pokemon const { data, error } = useRequest('/pokemon', name) if (error) return <h1>Something went wrong!</h1> if (!data) return <h1>Loading...</h1> return ( <div className='Card'> <span className='Card--id'>#{data.id}</span> <img className='Card--image' src={data.sprites.front_default} alt={name} /> <h1 className='Card--name'>{name}</h1> <span className='Card--details'> {data.types.map((poke) => poke.type.name).join(', ')} </span> </div> ) }

คุณสามารถดูแล้วว่า hook แบบกำหนดเองของเราทำให้สิ่งต่าง ๆ ง่ายขึ้นและยืดหยุ่นมากขึ้นได้อย่างไร ที่นี่เราแค่ต้องส่งชื่อโปเกมอนเพิ่มเติมเพื่อดึงข้อมูลเพื่อใช้ useRequest และจัดการทุกอย่างให้เรา

ฉันหวังว่าคุณจะเริ่มเพลิดเพลินกับห้องสมุดสุดเจ๋งนี้ — อย่างไรก็ตาม เรายังมีสิ่งที่จะค้นพบเพราะ SWR มีคุณสมบัติมากมาย และหนึ่งในนั้นคือ useSWRPages ซึ่งเป็นส่วนเกี่ยวสำหรับการแบ่งหน้าข้อมูลอย่างง่ายดาย ลองใช้เบ็ดนั้นในโครงการ

แบ่งหน้าข้อมูลของเราด้วย useSWRPages

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

ตอนนี้ มาสร้างไฟล์ใหม่ในรูทของโปรเจ็ usePagination.js และใช้เป็นฮุคแบบกำหนดเองสำหรับการแบ่งหน้า

 import React from 'react' import useSWR, { useSWRPages } from 'swr' import { Pokemon } from './components/Pokemon' export const usePagination = (path) => { const { pages, isLoadingMore, loadMore, isReachingEnd } = useSWRPages( 'pokemon-page', ({ offset, withSWR }) => { const url = offset || `https://pokeapi.co/api/v2${path}` const { data: result, error } = withSWR(useSWR(url)) if (error) return <h1>Something went wrong!</h1> if (!result) return <h1>Loading...</h1> return result.results.map((pokemon) => ( <Pokemon key={pokemon.name} pokemon={pokemon} /> )) }, (SWR) => SWR.data.next, [] ) return { pages, isLoadingMore, loadMore, isReachingEnd } }

อย่างที่คุณเห็น เราเริ่มต้นด้วยการนำเข้า useSWRPages ซึ่งเป็นตัวช่วยที่ช่วยให้สามารถแบ่งหน้าข้อมูลได้อย่างง่ายดาย ได้รับ 4 อาร์กิวเมนต์: คีย์ของหน้าคำขอ pokemon-page ซึ่งใช้สำหรับการแคชด้วย, ฟังก์ชันเพื่อดึงข้อมูลที่ส่งคืนส่วนประกอบหากดึงข้อมูลสำเร็จ และฟังก์ชันอื่นที่ใช้วัตถุ SWR และขอข้อมูลจาก หน้าถัดไป และอาร์เรย์ของการพึ่งพา

และเมื่อดึงข้อมูลแล้ว ฟังก์ชัน useSWRPages จะคืนค่าหลายค่า แต่ที่นี่เราต้องการ 4 ค่า ได้แก่ pages เป็นส่วนประกอบที่ส่งคืนพร้อมกับข้อมูล ฟังก์ชัน isLoadingMore ซึ่งจะตรวจสอบว่ามีการดึงข้อมูลอยู่หรือไม่ ฟังก์ชัน loadMore ที่ช่วยดึงข้อมูล ข้อมูลมากขึ้น และวิธีการ isReachingEnd ซึ่งกำหนดว่ายังมีข้อมูลให้ดึงหรือไม่

ตอนนี้ เรามี hook แบบกำหนดเองที่คืนค่าที่จำเป็นเพื่อแบ่งหน้าข้อมูล ตอนนี้เราสามารถย้ายไปที่ไฟล์ App.js และปรับแต่งได้เล็กน้อย

 import React from 'react' import { usePagination } from './usePagination' import './styles.css' export default function App() { const { pages, isLoadingMore, loadMore, isReachingEnd } = usePagination( '/pokemon' ) return ( <main className='App'> <h1>Pokedex</h1> <div>{pages}</div> <button onClick={loadMore} disabled={isLoadingMore || isReachingEnd} > Load more... </button> </main> ) }

เมื่อนำเข้า hook usePagination ตอนนี้เราสามารถส่งพา ธ เป็นพารามิเตอร์และรับค่าที่ส่งคืนได้ และเนื่องจาก pages เป็นส่วนประกอบ เราจึงไม่จำเป็นต้องวนซ้ำข้อมูลหรืออะไรทำนองนั้น

ต่อไป เราใช้ฟังก์ชัน loadMore บนปุ่มเพื่อดึงข้อมูลเพิ่มเติมและปิดใช้งานหากการดำเนินการดึงข้อมูลไม่เสร็จสิ้นหรือหากไม่มีข้อมูลให้ดึงข้อมูล

ยอดเยี่ยม! ด้วยการเปลี่ยนแปลงนั้น ตอนนี้เราสามารถเรียกดูบนรูทของโปรเจ็กต์และเริ่มต้นเซิร์ฟเวอร์ด้วยคำสั่งนี้เพื่อดูตัวอย่างแอปของเรา

 yarn start

หรือถ้าคุณใช้ npm:

 npm start

คุณควรเห็นว่าดึงข้อมูลสำเร็จแล้ว และหากคุณคลิกที่ปุ่ม SWR จะดึงข้อมูลใหม่

การแบ่งหน้า
การแบ่งหน้า (ตัวอย่างขนาดใหญ่)

จนถึงตอนนี้ เราได้เห็นไลบรารี SWR ในทางปฏิบัติแล้ว และฉันหวังว่าคุณจะพบคุณค่ากับมัน อย่างไรก็ตาม มันยังคงมีคุณสมบัติบางอย่างที่จะนำเสนอ มาดูฟังก์ชันเหล่านี้กันในหัวข้อถัดไป

คุณสมบัติอื่นๆ ของ SWR

ไลบรารี SWR มีสิ่งอำนวยความสะดวกมากมายที่ช่วยให้เราสร้างแอป React ได้ง่ายขึ้น

การตรวจสอบโฟกัสใหม่

เป็นคุณลักษณะที่ช่วยให้อัปเดตหรือตรวจสอบความถูกต้องอีกครั้งเพื่อให้ข้อมูลแม่นยำยิ่งขึ้นเมื่อคุณปรับโฟกัสหน้าเว็บใหม่หรือสลับไปมาระหว่างแท็บต่างๆ และโดยค่าเริ่มต้น ฟังก์ชันนี้จะถูกเปิดใช้งาน แต่คุณสามารถปิดใช้งานได้ต่อไปหากไม่เหมาะกับความต้องการของคุณ อาจมีประโยชน์โดยเฉพาะอย่างยิ่งถ้าคุณมีข้อมูลที่มีการอัพเดตความถี่สูง

เรียกข้อมูลตามช่วงเวลา

ไลบรารี SWR อนุญาตให้ดึงข้อมูลหลังจากระยะเวลาหนึ่ง อาจมีประโยชน์เมื่อข้อมูลของคุณเปลี่ยนแปลงด้วยความเร็วสูงหรือคุณจำเป็นต้องส่งคำขอใหม่เพื่อรับข้อมูลใหม่จากฐานข้อมูลของคุณ

การกลายพันธุ์ในท้องถิ่น

ด้วย SWR คุณสามารถตั้งค่าสถานะภายในเครื่องชั่วคราวที่จะอัปเดตโดยอัตโนมัติเมื่อมีการดึงข้อมูลใหม่ (การตรวจสอบซ้ำ) คุณลักษณะนี้มีให้ใช้งานโดยเฉพาะอย่างยิ่งเมื่อคุณจัดการกับแนวทางออฟไลน์ก่อน ซึ่งจะช่วยอัปเดตข้อมูลได้อย่างง่ายดาย

เลื่อนตำแหน่งการกู้คืน

คุณลักษณะนี้มีประโยชน์มาก โดยเฉพาะอย่างยิ่งเมื่อต้องจัดการกับรายการขนาดใหญ่ ช่วยให้คุณสามารถกู้คืนตำแหน่งการเลื่อนหลังจากกลับมาที่หน้า และไม่ว่าในกรณีใด มันจะเพิ่มความสามารถในการใช้งานแอปของคุณ

การดึงข้อมูลขึ้นอยู่กับ

SWR ให้คุณดึงข้อมูลที่ขึ้นอยู่กับข้อมูลอื่น ซึ่งหมายความว่าสามารถดึงข้อมูล A ได้ และเมื่อดำเนินการเสร็จสิ้น จะใช้เพื่อดึงข้อมูล B ในขณะที่หลีกเลี่ยงน้ำตก และคุณสมบัตินี้ช่วยคุณได้เมื่อคุณมีข้อมูลเชิงสัมพันธ์

ที่กล่าวว่า SWR ช่วยเพิ่มประสบการณ์ผู้ใช้ในเรื่องใด ๆ มีคุณลักษณะมากกว่านั้น และในหลายกรณี ควรใช้ผ่าน Fetch API หรือไลบรารี Axios

บทสรุป

ตลอดบทความนี้ เราได้เห็นแล้วว่าเหตุใด SWR จึงเป็นห้องสมุดที่ยอดเยี่ยม อนุญาตให้ดึงข้อมูลระยะไกลโดยใช้ React Hooks และช่วยให้ฟีเจอร์ขั้นสูงบางอย่างง่ายขึ้น เช่น การแบ่งหน้า การแคชข้อมูล การดึงข้อมูลตามช่วงเวลา การกู้คืนตำแหน่งการเลื่อน และอื่นๆ SWR เป็นแบ็กเอนด์ที่ไม่เชื่อเรื่องพระเจ้าซึ่งหมายความว่าสามารถดึงข้อมูลจาก API หรือฐานข้อมูลประเภทใดก็ได้ สรุปแล้ว SWR ช่วยเพิ่มประสบการณ์ผู้ใช้แอป React ของคุณอย่างมาก มันมีอนาคตที่สดใส และคุณควรจับตาดูมันหรือใช้มันให้ดีขึ้นในแอป React ถัดไปของคุณ

คุณสามารถดูตัวอย่างโครงการที่เสร็จสิ้นแล้วได้ที่นี่

ขอบคุณที่อ่าน!

ขั้นตอนถัดไป

คุณสามารถตรวจสอบลิงก์ต่อไปนี้ได้ ซึ่งจะช่วยให้คุณเข้าใจมากขึ้นนอกเหนือจากขอบเขตของบทช่วยสอนนี้

  • SWR
  • เอกสาร SWR

อ่านเพิ่มเติม เกี่ยวกับ SmashingMag:

  • ส่วนประกอบการจัดแต่งใน React
  • ตัวลดที่ดีขึ้นด้วย Immer
  • ส่วนประกอบที่มีลำดับสูงกว่าใน React
  • การสร้างส่วนประกอบ React แบบใช้ซ้ำได้โดยใช้ Tailwind