如何使用 Mirage.js 在 React 應用程式中建置和使用模擬 API
在開發全端應用程式時,前端工作的很大一部分依賴來自後端的即時數據。
上述困境表明,人們可能需要推遲使用者介面的開發,直到應用程式介面(API)已準備好供使用為止。然而,由於預期 API 已準備就緒而推遲前端開發的啟動可能會嚴重阻礙進度並延長專案的持續時間。
可以透過使用模擬 API 來實現此問題的合適解決方案。此類 API 允許使用模擬資料結構來開發和測試前端系統,而無需依賴真實的 API。
Mirage.js 模擬 API 入門
Mirage.js 是一個 JavaScript 函式庫,可讓您建立模擬 API,並在 Web 應用程式的用戶端上執行測試伺服器。這意味著您可以測試前端程式碼,而無需擔心真實後端 API 的可用性或行為。
為了利用 Mirage.js,有必要建立一組模擬 API 端點並指定這些端點預期傳遞的相應回應。隨後,Mirage.js 將擷取前端應用程式向 Web 伺服器發出的每個請求,並取代模擬回應。
一旦您的應用程式介面 (API) 得到充分開發和測試,在您的專案中實現它就變成了一個簡單的過程,只需要更新 Mirage.js 中的配置設定。這種簡化的方法可以實現無縫集成,同時將對現有功能或性能的干擾降至最低。
人們可以在關聯的 GitHub 儲存庫中找到該專案的原始程式碼。
使用 Mirage.js 建立模擬 API 伺服器
為了利用 Mirage.js 作為後端為 React 應用程式建立模擬 API,我們首先將在 React 中建立一個簡單的任務管理應用程式。在繼續這項工作之前,必須採取幾個初步步驟。首先,應該使用兩種可用方法之一來建立一個新的 React 應用程式。最初的方法涉及執行 create-react-app
命令列指令,這是一種廣泛認可的常規方法。相反,另一種途徑是透過實施 Vite 來建立 React 項目,Vite 是一種現代開發伺服器,因其快速效能而受到關注。在這些選項之間做出選擇後,必須透過套件管理器或 npm 註冊表安裝 Mirage.js 來引入必要的依賴項。
npm install --save-dev miragejs
為了建立一個捕獲傳入請求並模仿 API 答案的 Mirage.js 伺服器實例,請使用接受隨附配置物件的 createServer
方法。
上述實體包括環境上下文和我們的應用程式介面(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;
}
為了使命名空間與 API URL 的特定結構保持一致,您可以根據自己的要求靈活地對其進行個性化設定。此外,如有必要,您可以在命名空間中包含版本號,以確保與 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>,
)
將種子資料加入模擬 API
利用 Mirage.js 的內建記憶體資料庫,開發人員能夠使用初始種子資料預先載入模擬 API 進行測試,並有效管理客戶端應用程式產生的測試資料。此功能允許在模擬資料庫中無縫儲存和檢索測試數據,然後可以在客戶端應用程式中使用這些數據。
為了將初始資料合併到模擬 API 中,您應該在「server.js」檔案中的「models」物件之後立即包含以下程式碼行。
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 等函式庫來產生所需的測試數據,而不是對測試資料進行硬編碼。
定義模擬 API 路由
為了實現功能性模擬 API,需要建立多個可以容納 GET、POST 和 DELETE 請求的 API 端點。這些路由將作為我們模擬 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 端點互動並利用 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 鉤子以及適當的減速器函數。這種方法使我們能夠在所有元件之間維護一致的狀態樹,同時保持程式碼整潔和有組織。
const [todos, setTodos] = useState([]);
const [newTodo, setNewTodo] = useState({ title: '', body: '' });
const [loading, setLoading] = useState(true);
const [renderKey, setRenderKey] = useState(0);
在 Web 瀏覽器中初始化應用程式時,需要實作一種機制來檢索和顯示儲存在記憶體資料庫中的種子資料。為了實現這個目標,我們可以利用 React 提供的 useEffect 鉤子,將 fetch 函數呼叫封裝在其作用域內。這將確保在載入應用程式時檢索並顯示種子資料。
useEffect(() => {
fetch('/api/todos')
.then((response) => response.json())
.then((data) => {
setTodos(data.todos);
setLoading(false);
});
}, [renderKey]);
在 useEffect
掛鉤範圍內包含 renderKey
狀態有助於在託管系統正常運作時重新啟動本機操作資料庫中存在的任何新合併的資訊。
本質上,每當使用者在 Mirage.js 儲存庫中引入新的待辦事項資訊時,該元件都會經歷重新生成過程,以便直觀地反映修改後的資料。
將資料加入 API
為了方便透過 HTTP POST 請求新增數據,必須在應用程式介面 (API) 內實現邏輯結構。使用“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);
});
};
當使用者在指定的輸入欄位中輸入資料並按一下「新增待辦事項」按鈕時,系統會使用所提供的資訊更新「新待辦事項」的目前狀態。隨後,模擬的 HTTP POST 請求被傳送到 API,其請求正文中包含更新後的資料結構的實例,以便儲存在記憶體資料庫中。
成功的 POST 請求後,程式碼會透過將新建立的任務物件附加到「todos」數組來按程式更新「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
檔案中,以便在文件物件模型 (DOM) 中顯示它。
import TodoList from './components/TodoList';
//code ...
<TodoList />
事實上,在啟動開發伺服器後,人們可以檢索初始資料集,並透過新增和刪除資料來互動地修改其 React 應用程式中的模擬 API。
使用 Mock API 加速開發
無論是獨立進行工作還是在協作環境中,利用模擬 API 都提供了一種推進前端開發的有效方法。透過使用模擬 API,人們可以快速建立使用者介面並評估相關程式碼,而無需等待後端完成。