有没有办法在 React 中用 REST API 替换虚假的 MSW 数据?

问题描述 投票:0回答:0

我已经使用 Mock Service Worker 或 MSW 为我的 React 应用程序创建了一个可以正常工作的假服务器。我发现用我真正的 Django REST API 替换假后端很麻烦。

这是我的假后端

index.js

//import React from "react";
import { setupWorker, rest, createResponseComposition, context } from "msw";
import { v4 as uuid } from "uuid";

const delayedResponse = createResponseComposition(null, [
  context.delay("real"),
]);

const CACHE_KEY = "100-products-msw-plain";
const store = JSON.parse(localStorage.getItem(CACHE_KEY)) || {
 products: [],


};
function updateStore(newStore) {
  Object.assign(store, newStore);
  localStorage.setItem(CACHE_KEY, JSON.stringify(store));
}



const worker = setupWorker(
  // - AUTHORIZATION NOT REQUIRED -


  // LOGIN

  // GET ALL productS
  rest.get("/api/products", (req, res, ctx) => {

    const minimalProducts = store.products.map(({ id, title }) => ({
      id,
      title,
   
    }));
    return delayedResponse(() => res(ctx.json(minimalProducts)));
  }),
  // GET SINGLE product
  rest.get("/api/products/:pid", (req, res, ctx) => {
    const { pid } = req.params;
    const product = store.products.find(({ id }) => id === pid);
    return delayedResponse(() => res(ctx.json(product)));
  }),



);

// Register the Service Worker and enable the mocking
export default worker;

这是我的数据API

使用API.js

import React from "react";
import { useState, useMemo } from "react";

const URLS = {

  PRODUCTS: "/api/products/",
  PRODUCT: (id) => `/api/products/${id}`,

};

const get = (url) => fetch(url);
function useAPI() {

  const [isLoading, setLoading] = useState(false);
  const API = useMemo(() => {

    // common wrapper for all network requests
    const wrap = (promise) => {
      setLoading(true);
      return (
        promise
          // This is invoked regardless of result
          .finally(() => setLoading(false))
          // This is invoked for all server responses,
          // but .ok is only true for 20x and 30x responses
          .then((res) => {
       
            return res.json();
          })
          // Finally, this catches both network, auth, and server errors
          .catch((e) => {
          
            throw e;
          })
      );
    };

    // USER API

    //  API
    const loadProducts = () => wrap(get(URLS.PRODUCTS));
    const loadProduct = (id) => wrap(get(URLS.PRODUCT(id)));
  

    return {
   
      loadProducts,
      loadProduct,

    };
  }, []);

  return {

    isLoading,
    API,
  };
}

export default useAPI;

DataProvider.js

import PropTypes from 'prop-types';
import { useState, useMemo } from "react";
import React from "react";
import DataContext from "./DataContext";
import Loader from "./Loader";
import useAPI from "./useAPI";

function DataProvider({ children }) {
  const { isLoading, API } = useAPI();

  const [products, setProducts] = useState([]);
  const [currentId, setCurrentId] = useState(null);
  const [currentProduct, setCurrentProduct] = useState(null);

  const actions = useMemo(() => {

    const loadProducts = () => API.loadProducts().then(setProducts);
    const loadProduct = (id) => API.loadProduct(id).then(setCurrentProduct);
 
    const seeProduct = (id) => setCurrentId(id);
    const seeAllProducts = () => setCurrentId(null);

    return {

    
      loadProduct,
      loadProducts,
 
   
      seeAllProducts,
      seeProduct,
    
    
    };
  }, [API]);
  const value = {
    state: {
      products,
      currentId,
      currentProduct,
   
    },
    actions,
  };

  return (
    <DataContext.Provider value={value}>
      {isLoading && <Loader />}
      {children}
    </DataContext.Provider>
  );
}


export default DataProvider;

Django REST API json 数据:

     {
            "id": 1,
            "images": [
                {
                    "image": "/media/product-images/43c39863-3c9d-4229-a60f-a57c96fd3278.png"
                }
            ],
            "title": "Asus Zenbook",
            "image": null,
            "is_active": true,
     

        },
        {
            "id": 2,
            "images": [
                {
                    "image": "/media/product-images/f680b1ef-7563-4b10-9f68-b068c298a12a.png"
                }
            ],
            "title": "hp",
            "image": null,
            "is_active": true,
  
        },

我正在尝试用真正的 Python REST API 替换我的假 msw 后端。

我尝试添加服务器的 api 数据源如下:(注意 ~ 注意 const URLS)

使用API.js

import React from "react";
import { useState, useMemo } from "react";

const URLS = {

  PRODUCTS: `http://127.0.0.1:8000/api/products/`,
  PRODUCT: (id) => `http://127.0.0.1:8000//api/products/${id}`,

};

const get = (url) => fetch(url);
function useAPI() {

  const [isLoading, setLoading] = useState(false);
  const API = useMemo(() => {

    // common wrapper for all network requests
    const wrap = (promise) => {
      setLoading(true);
      return (
        promise
          // This is invoked regardless of result
          .finally(() => setLoading(false))
          // This is invoked for all server responses,
          // but .ok is only true for 20x and 30x responses
          .then((res) => {
       
            return res.json();
          })
          // Finally, this catches both network, auth, and server errors
          .catch((e) => {
          
            throw e;
          })
      );
    };

    // USER API

    //  API
    const loadProducts = () => wrap(get(URLS.PRODUCTS));
    const loadProduct = (id) => wrap(get(URLS.PRODUCT(id)));
  

    return {
   
      loadProducts,
      loadProduct,

    };
  }, []);

  return {

    isLoading,
    API,
  };
}

export default useAPI;

然后我在我的主 index.js 中评论了假的 msw,如图所示:(注意第 4 个导入)。

index.js

import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
//import backend from "./backend";

//backend.start();

createRoot(document.getElementById("root")).render(
    <React.StrictMode>
      <App />
    </React.StrictMode>
  );

运行我的代码显示此错误:

undefined is not a function (near '...}).map(_ref3 => {...')
useAllProducts@http://localhost:3000/static/js/bundle.js:756:9
AllProducts@http://localhost:3000/static/js/bundle.js:1208:73

useAllProducts.js

import React from "react";
import { useEffect } from "react";
import useData from "./useData";

function useAllProducts() {
  const loadProducts = useData(({ actions }) => actions.loadProducts);
  useEffect(() => void loadProducts(), [loadProducts]);
  return useData(({ state }) => state.products).map(({ id }) => id);
}

export default useAllProducts;

AllProducts.js

import React from "react";
import styled from "styled-components";

import { useAllProducts } from "../data";
import Product from "./Product";
//import AddAProduct from "./AddAProduct";

function AllProducts() {
  const obj = {};
  const products = useAllProducts();
  return (
    <Main>
   
      <h1>All my products</h1>
      {products.map((product) => (
        <Product key={product} id={product}/>
      ))}
   
    </Main>
  );
}

export default AllProducts;

虽然我的 Django 后端显示这个:

[30/Mar/2023 14:30:50] "GET /api/products/ HTTP/1.1" 200 4980
[30/Mar/2023 14:30:50] "GET /api/products/ HTTP/1.1" 200 4980

基本上 useAPi.js 可以正常工作。 React 没有正确匹配我的 Django API 返回的对象是不是一个问题?帮助。

reactjs django-rest-framework react-hooks es6-promise msw
© www.soinside.com 2019 - 2024. All rights reserved.