Если вы создаете веб-приложение с помощью React, Vue, Angular или любого другого вашего любимого front-end фреймворка, вам необходимо взаимодействовать с backend API для CRUD-операций. Допустим, вы хотите быстро создать прототип приложения, но у вас еще нет готовых бэкенд API, что делать в этом случае? Лучший способ – это иметь имитационные данные с поддельного сервера.
Как создать имитационные данные, у нас есть так много библиотек, которые могут помочь нам достичь этой цели, но в этом посте я рассматриваю использование miragejs с React.
Почему я рассматриваю именно эту библиотеку, хотя есть и другие популярные библиотеки, по двум причинам, первая – вам не нужно создавать/крутить другой сервер для загрузки ваших данных, например: http://localhost:3001, где работает ваш mock-сервер, но mirage работает на том же сервере разработки и позволяет вам получить доступ к данным, как будто вы работаете с реальным API, и второе, вы можете использовать mirage в качестве конечной точки API для написания сквозных тестов с помощью Cypress, я даже не думал о других вариантах, когда я получил 2 преимущества, просто создав mock-сервер с mirage, и он предлагает большой опыт разработчика, на мой взгляд.
Вы также можете использовать его для имитации конечных точек API с react-testing-library для написания юнит-тестов. Пожалуйста, обратитесь к документации для получения более подробной информации.
Давайте начнем, создадим react-приложение с помощью create-react-app и добавим это в index.js. Запускаем макет сервера только во время разработки.
// index.js
import React from "react";
import ReactDOM from "react-dom";
import { makeServer } from "./server";
import UsersLayout from "./users-layout";
// It creates the mock server only in development mode
if (process.env.NODE_ENV === "development") {
makeServer({ environment: "development" });
}
const App = () => <UsersLayout />;
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);Создайте server.js, где настоящее волшебство происходит с меньшим количеством кода,
// server.js
import { createServer, Model } from "miragejs";
export function makeServer({ environment = "test" } = {}) {
let server = createServer({
environment,
models: {
user: Model,
},
seeds(server) {
server.create("user", { id: 1, name: "Bob Jhon" });
server.create("user", { id: 2, name: "Alice" });
},
routes() {
this.namespace = "api";
this.get("/users", (schema) => schema.users.all());
// To increment the id for each user inserted,
// Mirage auto creates an id as string if you don't pass one
let newId = 3
this.post("/users", (schema, request) => {
const attrs = JSON.parse(request.requestBody);
attrs.id = newId++
return schema.users.create(attrs);
});
this.delete("/users/:id", (schema, request) => {
const id = request.params.id;
return schema.users.find(id).destroy();
});
},
});
return server;
}Метод seeds() засеет нашу модель пользователя некоторыми начальными данными, чтобы мы могли сразу начать ее использовать, вы можете оставить его пустым, если хотите начать с пустой коллекции пользователей.
Определите все ваши маршруты API в методе routes() и вы можете определить ваше пространство имен API с помощью this.namespace = ‘api’, чтобы вам не пришлось повторять его во всех маршрутах, например: this.get(‘/api/users’). Здесь у меня есть три маршрута для GET, POST и DELETE пользователя.
Вам нужно создать модель с помощью mirage Model и с ее помощью вы можете получить доступ к данным из схемы, если вы внимательно посмотрите, я создал модель пользователя с именем user, но доступ к ней как schema.users.all(), mirage создает множественную коллекцию для нас, глядя на имя модели, хорошая практика – сохранять единственные имена для ваших моделей.
Mirage предлагает другие методы на схеме для добавления и удаления элемента из коллекции, см. delete и post API маршруты в примере кода выше.
Вот и все, давайте напишем React-часть кода, чтобы мы могли использовать поддельный API Mirage с помощью fetch или axios, я использую fetch.
// users-layout.js
import React, { useState, useEffect, useCallback } from "react";
import { useFetch } from "./use-fetch";
export default function UsersLayout() {
const [users, setUsers] = useState([]);
const { data, loading: userLoading, error: userError } = useFetch(
"/api/users"
);
const [name, setName] = useState("");
const [isUpdating, setIsUpdating] = useState(false);
useEffect(() => {
if (data) {
setUsers(data.users);
}
}, [data]);
const onAddUser = useCallback(
async (e) => {
e.preventDefault();
try {
setIsUpdating(true);
const res = await fetch("/api/users", {
method: "POST",
body: JSON.stringify({ name }),
});
const data = await res.json();
setUsers((users) => users.concat(data.user));
setIsUpdating(false);
setName("");
} catch (error) {
throw error;
}
},
[name]
);
return (
<>
<form onSubmit={onAddUser}>
<input
type="text"
onChange={(e) => setName(e.target.value)}
value={name}
/>
<button type="submit" disabled={isUpdating}>
{isUpdating ? "Updating..." : "Add User"}
</button>
</form>
{userError && <div>{userError.message}</div>}
<ul>
{!userLoading &&
users.map((user) => <li key={user.id}>{user.name}</li>)}
</ul>
</>
);
}И в качестве бонуса в приведенном выше коде я написал пользовательский хук для получения данных useFetch с любых конечных точек API. Давайте посмотрим на код для useFetch
// use-fetch.js
import { useEffect, useState, useRef } from "react";
/**
* Hook to fetch data from any API endpoints
*/
export const useFetch = (url) => {
const [state, setState] = useState({
data: null,
loading: true,
error: null,
});
const isCurrent = useRef(true);
useEffect(() => {
return () => {
isCurrent.current = false;
};
}, []);
useEffect(() => {
setState((state) => ({ ...state, loading: true }));
const getData = async () => {
try {
const res = await fetch(url);
const data = await res.json();
// If calling component unmounts before the data is
// fetched, then there is a warning, "Can't perform
// React state update on an unmounted component"
// it may introduce side-effects, to avoid this, useRef to
// check for current reference.
if (isCurrent.current) {
setState((state) => ({
...state,
data,
loading: false,
error: null,
}));
}
} catch (error) {
setState((state) => ({ ...state, error: error }));
}
};
getData();
}, [url]);
return state;
};Вот и все, с небольшими усилиями вы можете подделать данные с помощью поддельного API-сервера, используя miragejs. И mirage хорошо масштабируется с большими приложениями, я проверил это в бою и надеюсь, что вы найдете это полезным. Попробуйте на своем следующем проекте. Это сэкономит много времени во время разработки.
Оригинал: “https://www.codementor.io/@kpunith8/how-to-create-fake-api-server-for-react-apps-with-miragejs-1baqn9nc4d”