วิธีสร้างและใช้ Mock API ในแอป React โดยใช้ Mirage.js
เมื่อพัฒนาแอปพลิเคชันแบบฟูลสแตก ส่วนสำคัญของงานฟรอนต์เอนด์จะต้องอาศัยข้อมูลแบบเรียลไทม์จากแบ็กเอนด์
สถานการณ์ที่กล่าวมาข้างต้นชี้ให้เห็นว่าเราอาจจำเป็นต้องเลื่อนการพัฒนาส่วนต่อประสานกับผู้ใช้ออกไปจนกว่าจะถึงเวลาที่ Application Programming Interface (API) ได้ถูกเตรียมไว้สำหรับการใช้งาน อย่างไรก็ตาม การชะลอการเริ่มต้นการพัฒนาส่วนหน้าโดยคาดหวังถึงความพร้อมของ API สามารถขัดขวางความคืบหน้าได้อย่างมาก และทำให้ระยะเวลาการดำเนินการยืดเยื้อออกไป
วิธีแก้ปัญหาที่เหมาะสมสำหรับปัญหานี้สามารถทำได้โดยการใช้ API จำลอง API ดังกล่าวช่วยให้สามารถพัฒนาและทดสอบระบบส่วนหน้าโดยใช้โครงสร้างข้อมูลจำลอง โดยไม่ต้องพึ่งพา API ที่แท้จริง
เริ่มต้นใช้งาน Mirage.js Mock API
Mirage.js คือไลบรารี JavaScript ที่ช่วยให้คุณสร้าง API จำลอง พร้อมด้วยเซิร์ฟเวอร์ทดสอบที่ทำงานบนฝั่งไคลเอ็นต์ของเว็บแอปพลิเคชันของคุณ ซึ่งหมายความว่าคุณสามารถทดสอบโค้ดส่วนหน้าได้โดยไม่ต้องกังวลกับความพร้อมใช้งานหรือพฤติกรรมของ API แบ็กเอนด์จริงของคุณ
ในการใช้ Mirage.js จำเป็นต้องสร้างชุดตำแหน่งข้อมูลจำลอง API และระบุการตอบกลับที่เกี่ยวข้องซึ่งคาดว่าจะส่งมอบตำแหน่งข้อมูลเหล่านี้ ต่อจากนั้น Mirage.js จะบันทึกทุกคำขอที่ทำโดยแอปพลิเคชันส่วนหน้าของคุณไปยังเว็บเซิร์ฟเวอร์และแทนที่การตอบสนองจำลองแทน
เมื่อ Application Programming Interface (API) ของคุณได้รับการพัฒนาและทดสอบอย่างสมบูรณ์แล้ว การนำไปใช้ในโปรเจ็กต์ของคุณจะกลายเป็นกระบวนการที่ไม่ซับซ้อนซึ่งเพียงแค่อัปเดตการตั้งค่าการกำหนดค่าภายใน Mirage.js แนวทางที่ได้รับการปรับปรุงนี้ช่วยให้สามารถบูรณาการได้อย่างราบรื่นโดยรบกวนฟังก์ชันการทำงานหรือประสิทธิภาพที่มีอยู่น้อยที่สุด
อาจค้นหาซอร์สโค้ดสำหรับโปรเจ็กต์นี้ภายในที่เก็บ GitHub ที่เกี่ยวข้อง
สร้างเซิร์ฟเวอร์ Mock API ด้วย Mirage.js
ในการสร้าง API จำลองสำหรับแอปพลิเคชัน React ที่ใช้ Mirage.js เป็นแบ็กเอนด์ เราจะเริ่มสร้างแอปพลิเคชันการจัดการงานที่ตรงไปตรงมาใน React ก่อนที่จะดำเนินการตามความพยายามนี้ มีขั้นตอนเบื้องต้นหลายประการที่ต้องดำเนินการ ประการแรก ควรสร้างแอปพลิเคชัน React ใหม่โดยใช้วิธีใดวิธีหนึ่งจากสองวิธีที่มีอยู่ วิธีการเริ่มต้นเกี่ยวข้องกับการดำเนินการคำสั่งบรรทัดคำสั่ง create-react-app
ซึ่งเป็นวิธีการทั่วไปที่ได้รับการยอมรับอย่างกว้างขวาง ในทางกลับกัน เส้นทางอื่นเกี่ยวข้องกับการตั้งค่าโปรเจ็กต์ React ผ่านการปรับใช้ Vite ซึ่งเป็นเซิร์ฟเวอร์การพัฒนาสมัยใหม่ที่ได้รับความโดดเด่นเนื่องจากประสิทธิภาพที่รวดเร็ว เมื่อเลือกตัวเลือกเหล่านี้แล้ว จำเป็นต้องแนะนำการขึ้นต่อกันที่จำเป็นโดยการติดตั้ง Mirage.js ผ่านทางตัวจัดการแพ็คเกจหรือรีจิสทรี npm
npm install --save-dev miragejs
ในการสร้างอินสแตนซ์เซิร์ฟเวอร์ Mirage.js ที่รวบรวมคำขอที่เข้ามาและเลียนแบบคำตอบ API ให้ใช้เมธอด createServer
ซึ่งยอมรับออบเจ็กต์การกำหนดค่าที่มาพร้อมกัน
เอนทิตีที่กล่าวมาข้างต้นประกอบด้วยทั้งบริบทด้านสิ่งแวดล้อมและรูปแบบการตั้งชื่อที่เกี่ยวข้องสำหรับ Application Programming Interface (API) ของเรา โดยเฉพาะอย่างยิ่ง พารามิเตอร์สภาพแวดล้อมแสดงถึงระยะปัจจุบันของวงจรชีวิตของ API เช่น สถานะการพัฒนา ในขณะที่เนมสเปซทำหน้าที่เป็นการกำหนดเบื้องต้นที่ต่อท้ายจุดสิ้นสุด API แต่ละรายการ ดังนั้นจึงให้ตัวระบุที่ไม่ซ้ำกัน
อันที่จริง ฉันจะสร้างไฟล์ src/server.js
ใหม่และรวมข้อมูลโค้ดที่ให้มาไว้ภายใน สคริปต์ผลลัพธ์จะจัดการกับคำขอจากลูกค้าที่ค้นหาข้อมูลเกี่ยวกับผลิตภัณฑ์หรือบริการที่นำเสนอโดยบริษัทของคุณ ก่อนอื่นจะแยกวิเคราะห์คำขอที่เข้ามาเพื่อกำหนดประเภทของคำขอ ไม่ว่าจะเป็นเพื่อดูรายละเอียดผลิตภัณฑ์หรือข้อมูลราคา ตามการตัดสินใจนี้ ระบบจะดึงข้อมูลที่เกี่ยวข้องออกจากฐานข้อมูลโดยใช้คีย์หลักเป็นตัวระบุ หากสำเร็จ เซิร์ฟเวอร์จะส่งการตอบกลับที่มีข้อมูลที่ร้องขอในรูปแบบ JSON อย่างไรก็ตาม หากคำขอล้มเหลวเนื่องจากพารามิเตอร์อินพุตไม่ถูกต้อง ข้อความแสดงข้อผิดพลาดจะถูกส่งกลับแทน
import { createServer, Model } from 'miragejs';
const DEFAULT_CONFIG = {
environment: "development",
namespace: "api",
};
export function makeServer({ environment, namespace } =
DEFAULT_CONFIG) {
let server = createServer({
environment,
namespace,
models: {
Todo: Model,
},
});
return server;
}
เพื่อจัดตำแหน่งเนมสเปซให้สอดคล้องกับโครงสร้างเฉพาะของ URL ของ API คุณมีความยืดหยุ่นในการปรับแต่งเนมสเปซตามความต้องการของคุณ นอกจากนี้ หากจำเป็น คุณอาจรวมหมายเลขเวอร์ชันในเนมสเปซเพื่อให้แน่ใจว่าเข้ากันได้กับการอัปเดตหรือการแก้ไข API ในอนาคต การทำเช่นนี้ เมื่อ API แบ็กเอนด์ของคุณได้รับการพัฒนาและใช้งานได้อย่างสมบูรณ์ การรวมเข้ากับอินเทอร์เฟซผู้ใช้ของคุณอย่างราบรื่นจะต้องมีการปรับเปลี่ยนฐานโค้ดของคุณเพียงเล็กน้อยเท่านั้น
นอกจากนี้ เราอาจระบุสคีมาข้อมูลภายในการตั้งค่าการกำหนดค่าของเซิร์ฟเวอร์เพื่อเลียนแบบกระบวนการจัดเก็บและเรียกค้นข้อมูลในบริบทจำลอง
แท้จริงแล้ว เพื่อเริ่มต้นการทำงานของ Mirage.js เราจะต้องนำเข้าอ็อบเจ็กต์เซิร์ฟเวอร์ดังกล่าวไปยังไฟล์ index.jsx หรือ main.jsx สามารถทำได้โดยผ่านกระบวนการต่อไปนี้:
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import { makeServer } from './server';
if ( process.env.NODE_ENV === 'development' &&
typeof makeServer === 'function'
) {
makeServer();}
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App/>
</React.StrictMode>,
)
เพิ่มข้อมูลเริ่มต้นลงใน Mock API
การใช้ฐานข้อมูลหน่วยความจำภายในของ Mirage.js ช่วยให้นักพัฒนาสามารถโหลด Mock API ของตนล่วงหน้าด้วยข้อมูลเริ่มต้นสำหรับวัตถุประสงค์ในการทดสอบ รวมถึงการจัดการข้อมูลการทดสอบที่สร้างโดยแอปพลิเคชันไคลเอนต์ได้อย่างมีประสิทธิภาพ คุณลักษณะนี้ช่วยให้สามารถจัดเก็บและดึงข้อมูลการทดสอบภายในฐานข้อมูลจำลองได้อย่างราบรื่น ซึ่งอาจนำไปใช้ในแอปพลิเคชันไคลเอนต์ได้
หากต้องการรวมข้อมูลเริ่มต้นลงใน mock API คุณควรรวมบรรทัดโค้ดต่อไปนี้ไว้หลังออบเจ็กต์’models’ภายในไฟล์’server.js'
seeds(server) {
server.create('Todo', {
title: 'item no 1',
body:
'Do something nice for someone I care about',
});
server.create('Todo', {
title: 'item no 2',
body:
'Memorize the fifty states and their capitals.',
});
server.create('Todo', {
title: 'item no 3',
body:
'Watch a classic movie.',
});
},
ฟังก์ชัน seeds จะเติมเซิร์ฟเวอร์ Mirage.js ด้วยรายการสิ่งที่ต้องทำสามรายการ โดยแต่ละรายการมีชื่อและคำอธิบาย อีกทางเลือกหนึ่ง แทนที่จะเข้ารหัสข้อมูลการทดสอบอย่างหนัก คุณสามารถรวมไลบรารี เช่น Faker.js เพื่อสร้างข้อมูลการทดสอบที่ต้องการได้
กำหนดเส้นทาง Mock API
เพื่อใช้งาน Mock API จำเป็นต้องสร้างจุดสิ้นสุด API หลายแห่งที่สามารถรองรับคำขอ GET, POST และ DELETE ได้ เส้นทางเหล่านี้จะทำหน้าที่เป็นรากฐานของฟังก์ชันการทำงานของ mock API ของเรา ซึ่งช่วยให้เราสามารถจำลองการโต้ตอบต่างๆ กับเซิร์ฟเวอร์และทดสอบสถานการณ์ต่างๆ ด้วยการกำหนดเส้นทางเหล่านี้ เราสามารถจำลองจุดสิ้นสุด API จริงได้อย่างมีประสิทธิภาพ และตรวจสอบพฤติกรรมของมันภายใต้เงื่อนไขที่แตกต่างกัน
ด้านล่างชุดข้อมูลเริ่มต้น ให้รวมโค้ดที่ให้มาดังนี้:
routes() {
this.namespace = 'api/todos';
this.get('/', (schema, request) => {
return schema.all('Todo');
});
this.post('/', (schema, request) => {
let attrs = JSON.parse(request.requestBody);
return schema.create('Todo', attrs);
});
this.delete('/:id', (schema, request) => {
let id = request.params.id;
return schema.find('Todo', id).destroy();
});
}
สร้างไคลเอนต์ React
เมื่อจำลอง API ของเราถูกสร้างขึ้นแล้ว เราจะดำเนินการสร้างไคลเอนต์ React ซึ่งจะเชื่อมต่อกับและใช้จุดสิ้นสุด API คุณได้รับอนุญาตให้จ้างไลบรารีส่วนประกอบอินเทอร์เฟซผู้ใช้ใดก็ได้ที่คุณต้องการ อย่างไรก็ตาม เพื่อความชัดเจน บทช่วยสอนนี้จะใช้ Chakra UI เพื่อปรับปรุงรูปลักษณ์ของแอปพลิเคชัน
ขั้นแรก ให้ติดตั้งการขึ้นต่อกันเหล่านี้:
npm install @chakra-ui/react @emotion/react @emotion/styled framer-motion
ที่จริงแล้ว ให้เราดำเนินการสร้างอินสแตนซ์ใหม่ของไฟล์ TodoList.jsx ซึ่งครอบคลุมบล็อกโค้ดที่ตามมา:
import React, { useState, useEffect } from 'react';
import {
Button,
Box,
Container,
Text,
Input,
FormControl,
Flex,
} from '@chakra-ui/react';
เมื่อพิจารณาถึงงานที่มีอยู่ จะเป็นความรอบคอบในการพัฒนาส่วนประกอบการทำงานที่ครอบคลุมองค์ประกอบที่จำเป็นสำหรับการแสดงส่วนต่อประสานผู้ใช้รายการสิ่งที่ต้องทำ รวมถึงช่องป้อนข้อมูลที่อำนวยความสะดวกในการเพิ่มงานใหม่ เช่นเดียวกับการแจงนับของงานปัจจุบัน
export default function TodoList() {
return (
<Container>
<Text fontSize="xl" mb={4}>Todo List</Text>
<FormControl mb={4}>
<Input
type="text"
name="body"
value={newTodo.body}
onChange={handleInputChange}/>
</FormControl>
<Button colorScheme="teal" onClick={handleAddTodo}> Add Todo</Button>
{loading ? ( <Text>Loading...</Text> ) : (
todos.map((todo) => (
<Box key={todo.id} mb={2} p={2} borderWidth="1px">
<Flex align="center">
<Text flex="1">{todo.body}</Text>
<Button
colorScheme="red"
size="sm"
onClick={() => handleDelete(todo.id)}>Delete
</Button>
</Flex>
</Box>
))
)}
</Container>
);
}
รายการหนึ่งสำหรับการเพิ่มรายการลงในรายการ (ADD\_ITEM) และอีกรายการหนึ่งสำหรับการลบรายการออกจากรายการ (REMOVE\_ITEM) การดำเนินการเหล่านี้ควรถูกส่งโดยตัวจัดการที่เกี่ยวข้องเพื่อตอบสนองต่ออินพุตของผู้ใช้หรือเหตุการณ์อื่น ๆ ที่เกี่ยวข้อง ในการจัดการสถานะของแอปพลิเคชัน เราจะใช้ useReducer hook พร้อมกับฟังก์ชันตัวลดที่เหมาะสม แนวทางนี้ช่วยให้เราสามารถรักษาแผนผังสถานะที่สอดคล้องกันในทุกองค์ประกอบ ในขณะเดียวกันก็รักษาโค้ดของเราให้สะอาดและเป็นระเบียบ
const [todos, setTodos] = useState([]);
const [newTodo, setNewTodo] = useState({ title: '', body: '' });
const [loading, setLoading] = useState(true);
const [renderKey, setRenderKey] = useState(0);
เมื่อเริ่มต้นแอปพลิเคชันภายในเว็บเบราว์เซอร์ จำเป็นต้องใช้กลไกในการดึงและแสดงข้อมูลเริ่มต้นที่จัดเก็บไว้ในฐานข้อมูลในหน่วยความจำ เพื่อให้บรรลุวัตถุประสงค์นี้ เราสามารถใช้ฮุก useEffect
ที่ได้รับจาก React โดยห่อหุ้มการเรียกฟังก์ชัน fetch
ภายในขอบเขตของมัน สิ่งนี้จะช่วยให้มั่นใจได้ว่าข้อมูลเริ่มต้นจะถูกดึงและแสดงเมื่อโหลดแอปพลิเคชัน
useEffect(() => {
fetch('/api/todos')
.then((response) => response.json())
.then((data) => {
setTodos(data.todos);
setLoading(false);
});
}, [renderKey]);
การรวมสถานะ renderKey
ภายในขอบเขตของฮุก useEffect
ทำหน้าที่อำนวยความสะดวกในการเปิดใช้งานข้อมูลที่รวมใหม่ใด ๆ ที่มีอยู่ในฐานข้อมูลการปฏิบัติงานในพื้นที่ของเราเมื่อใดก็ตามที่ระบบโฮสต์ทำงานอย่างถูกต้อง
โดยพื้นฐานแล้ว เมื่อใดก็ตามที่ผู้ใช้แนะนำข้อมูลสิ่งที่ต้องทำใหม่ภายในพื้นที่เก็บข้อมูล Mirage.js ส่วนประกอบจะเข้าสู่กระบวนการสร้างใหม่เพื่อสะท้อนข้อมูลที่แก้ไขด้วยสายตา
การเพิ่มข้อมูลลงใน API
เพื่ออำนวยความสะดวกในการเพิ่มข้อมูลผ่านการร้องขอ HTTP POST จึงจำเป็นอย่างยิ่งที่จะต้องนำโครงสร้างเชิงตรรกะไปใช้ภายใน Application Programming Interface (API) เมื่อประสบความสำเร็จในการใช้ hook useEffect
ทันที ให้รวมการดำเนินการต่อไปนี้
const handleInputChange = (e) => {
const { name, value } = e.target;
setNewTodo((prevTodo) => ({ ...prevTodo, [name]: value }));
};
const handleAddTodo = () => {
setLoading(true);
fetch('/api/todos', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(newTodo),
}).then((response) => response.json()).then((createdTodo) => {
setTodos((prevTodos) => [createdTodo, ...prevTodos]);
setNewTodo({ title: '', body: '' });
setRenderKey((prevKey) => prevKey \+ 1);
setLoading(false);
}).catch((error) => {
console.error('Error adding todo:', error);
setLoading(false);
});
};
เมื่อป้อนข้อมูลภายในช่องป้อนข้อมูลที่กำหนดและคลิกที่ปุ่ม"เพิ่มสิ่งที่ต้องทำ"โดยผู้ใช้ ระบบจะอัปเดตสถานะปัจจุบันของ"newTodo"ด้วยข้อมูลที่ให้ไว้ ต่อจากนั้น คำขอ HTTP POST จำลองจะถูกส่งไปยัง API ที่มีอินสแตนซ์ของโครงสร้างข้อมูลที่อัปเดตภายในเนื้อหาคำขอเพื่อจัดเก็บภายในฐานข้อมูลในหน่วยความจำ
เมื่อคำขอ POST สำเร็จ รหัสจะอัปเดตอาร์เรย์"todos"ตามขั้นตอนโดยการต่อท้ายออบเจ็กต์งานที่สร้างขึ้นใหม่ จากนั้นจะแจ้งให้องค์ประกอบฟังก์ชัน React เข้ารับการประเมินอีกครั้ง โดยจะแสดงรายการสิ่งที่ต้องทำที่อัปเดตภายในรายการบนหน้าด้วยสายตา
คำขอจำลอง API ลบ
ในการลบข้อมูลผ่านคำขอ DELETE จำลอง API จำเป็นต้องสร้างเฟรมเวิร์กเชิงตรรกะสำหรับกระบวนการนี้ โดยพื้นฐานแล้ว สิ่งนี้เกี่ยวข้องกับการส่งคำขอ DELETE โดยมีวัตถุประสงค์เพื่อกำจัดงานที่กำหนดออกจากฐานข้อมูลชั่วคราว ดังนั้น หากการดำเนินการพิสูจน์ได้ว่ามีประสิทธิผล ก็จำเป็นต้องแก้ไขทั้งรายการงานที่ค้างอยู่และตัวบ่งชี้การโหลด เพื่อแสดงว่าขั้นตอนการลบได้รับการดำเนินการเรียบร้อยแล้ว
const handleDelete = (id) => {
let deleteInProgress = true;
fetch(`/api/todos/${id}`, {
method: 'DELETE',
}).then((response) => {
if (response.status === 204) {
return null;
} else {
return response.json();
}
}) .then((data) => {
if (data && data.error) {
console.error('Error deleting todo:', data.error);
} else {
setTodos((prevTodos) => prevTodos.filter((todo) => todo.id !== id));
setRenderKey((prevKey) => prevKey \+ 1);
}
deleteInProgress = false;
}).catch((error) => {
console.error('Error deleting todo:', error);
deleteInProgress = false;
}) .finally(() => {
setLoading(deleteInProgress);
});
};
โปรดทราบว่าวิธีนี้สามารถลบได้เฉพาะข้อมูลที่เพิ่งเพิ่มเข้ามาเท่านั้น ไม่ใช่ชุดข้อมูลเริ่มต้น
รวมส่วนประกอบ TodoList
ไว้ในไฟล์ App.jsx
เพื่อแสดงภายใน Document Object Model (DOM)
import TodoList from './components/TodoList';
//code ...
<TodoList />
อันที่จริง เมื่อเริ่มต้นเซิร์ฟเวอร์การพัฒนา เราอาจดึงชุดข้อมูลเริ่มต้นและแก้ไข API จำลองภายในแอปพลิเคชัน React แบบโต้ตอบโดยทั้งการเพิ่มและการลบข้อมูล
การใช้ Mock API เพื่อเร่งการพัฒนา
การใช้ Mocking API นำเสนอวิธีการที่มีประสิทธิภาพในการพัฒนาส่วนหน้า ทั้งเมื่อทำงานโดยอิสระหรือภายในสภาพแวดล้อมการทำงานร่วมกัน ด้วยการใช้ Mock API เราสามารถสร้างอินเทอร์เฟซผู้ใช้และประเมินโค้ดที่เกี่ยวข้องได้อย่างรวดเร็ว โดยไม่ต้องรอให้แบ็คเอนด์เสร็จสมบูรณ์