Contents

วิธีสร้างและใช้ Mock API ในแอป React โดยใช้ Mirage.js

เมื่อพัฒนาแอปพลิเคชันแบบฟูลสแตก ส่วนสำคัญของงานฟรอนต์เอนด์จะต้องอาศัยข้อมูลแบบเรียลไทม์จากแบ็กเอนด์

สถานการณ์ที่กล่าวมาข้างต้นชี้ให้เห็นว่าเราอาจจำเป็นต้องเลื่อนการพัฒนาส่วนต่อประสานกับผู้ใช้ออกไปจนกว่าจะถึงเวลาที่ Application Programming Interface (API) ได้ถูกเตรียมไว้สำหรับการใช้งาน อย่างไรก็ตาม การชะลอการเริ่มต้นการพัฒนาส่วนหน้าโดยคาดหวังถึงความพร้อมของ API สามารถขัดขวางความคืบหน้าได้อย่างมาก และทำให้ระยะเวลาการดำเนินการยืดเยื้อออกไป

วิธีแก้ปัญหาที่เหมาะสมสำหรับปัญหานี้สามารถทำได้โดยการใช้ API จำลอง API ดังกล่าวช่วยให้สามารถพัฒนาและทดสอบระบบส่วนหน้าโดยใช้โครงสร้างข้อมูลจำลอง โดยไม่ต้องพึ่งพา API ที่แท้จริง

เริ่มต้นใช้งาน Mirage.js Mock API

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

/th/images/laptop-with-code-on-the-screen.jpg

ในการใช้ 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 เราสามารถสร้างอินเทอร์เฟซผู้ใช้และประเมินโค้ดที่เกี่ยวข้องได้อย่างรวดเร็ว โดยไม่ต้องรอให้แบ็คเอนด์เสร็จสมบูรณ์