跳到主要内容
JackSparrow414
返回

React应用入门(二)发送请求并Mock数据

本文导航

展开本文导航

React应用入门(二)发送请求并Mock数据

上一篇文章中,写了一个简单的Form表单,但是并没有提到前端向后端发送请求、以及接收到响应之后表单如何处理。本篇文章将完成这一部分

环境准备

在项目根目录下安装axios,qs,mockjs,运行下列命令

npm install axios qs mockjs

查看控制台是否有报错

注意:如果有报错,一定先解决npm install报错问题再进行后续的步骤

发送请求

axios

axios是一个类似于ajax的一个东东。Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中,来自于axios中文说明

在src文件夹下新建api文件夹,在这里处理所有发起对后端API的调用,至于项目结构和项目的搭建,参考本系列的第一章

mkdir api

调用示例基本如下

axios.request({
  url: 'method url',
  method: 'POST GET DELETE PUT',
  header: {'Content-Type': 'application/json'},
  data: requestData,
  responseType: 'json'
}).then(response => {
  retrun response.data
}).catch(error => {
  error.message
})

更多写法请参考官方文档,里面说的很详细。

全局实例

所有对后端API的请求统一由一个axios实例来完成,在这个实例中,我们可以配置所有请求的统一前缀。

在api文件夹下创建request.js文件,文件内容目前如下

import axios from "axios";
const service = axios.create({
  baseURL: "http://localhost:8081/badminton-community",
});
export default service;

虽然axios也有请求前的拦截器、和请求后的拦截器。但是我这里并没有添加,因为我们目前的功能暂时只需要一个baseUrl,不做过多引入,以免知识点太多而忽略了本篇文章的主要思路。后续在用到的时候会再次介绍

具体API请求

在api文件夹下新建loginForm.js文件,代表这个文件处理组件LoginForm中的请求

目前我们的场景是

这里我们需要做的就是发起请求,并接收响应数据,文件内容如下

import service from "./request";
import responseData from "../mocks/loginFormData";
const qs = require("qs");
export const login = loginFormData => {
  console.log("api---------------->");
  return service
    .request({
      url: "/login",
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      data: qs.stringify(loginFormData),
      responseType: "json",
    })
    .then(response => {
      console.log(response.data);
      //    返回数据
      return response.data;
    })
    .catch(error => {
      error.message;
    });
};

先引入axios全局实例

然后定义了一个login的函数,参数名字为loginFormData。对于后端的同学,如果看不懂箭头函数,强烈推荐这个前端语法全解析的文档,内容清晰明了,示例简单易懂。

具体组件中调用发起API调用的函数

已经有了发起API调用的函数,那么我们接下来要处理的就是将具体组件上和API调用的逻辑组合在一起,完成页面的联动

回到LoginForm组件中,在onSubmit中添加响应的处理

import { LoadingButton } from "@mui/lab";
import { IconButton, InputAdornment, Stack, TextField } from "@mui/material";
import { Icon } from "@iconify/react";
import eyeFill from "@iconify/icons-eva/eye-fill";
import eyeOffFill from "@iconify/icons-eva/eye-off-fill";
import { useFormik, Form, FormikProvider } from "formik";
import * as Yup from "yup";
import React from "react";
import { useState } from "react";
import { login } from "../../../api/loginForm";
export default function LoginForm() {
  const [showPassword, setShowPassword] = useState(false);
  const handleShowPassword = () => {
    setShowPassword(show => !show);
  };
  // 定义验证规则
  const LoginSchema = Yup.object().shape({
    email: Yup.string()
      .email("Email must be a valid email address")
      .required("Email is required"),
    password: Yup.string().required("Password is required"),
  });
  const formik = useFormik({
    initialValues: {
      email: "",
      password: "",
      remember: true,
    },
    validationSchema: LoginSchema,
    onSubmit: (values, props) => {
      console.log("request-------->");
      login(values).then(data => {
        console.log(data);
        // 成功之后将setSubmitting设置为false
        props.setSubmitting(false);
      });
      console.log("response------->");
    },
  });
  const { errors, touched, values, isSubmitting, handleSubmit, getFieldProps } =
    formik;

  return (
    <FormikProvider value={formik}>
      <Form autoComplete="off" noValidate onSubmit={handleSubmit}>
        <Stack spacing={3}>
          <TextField
            autoComplete="username"
            type="email"
            label="Email Address"
            {...getFieldProps("email")}
            error={Boolean(touched.email && errors.email)}
            helperText={touched.email && errors.email}
          />
          <TextField
            autoComplete="current-password"
            type={showPassword ? "text" : "password"}
            label="Password"
            {...getFieldProps("password")}
            InputProps={{
              endAdornment: (
                <InputAdornment position="end">
                  <IconButton onClick={handleShowPassword} edge="end">
                    <Icon icon={showPassword ? eyeFill : eyeOffFill}></Icon>
                  </IconButton>
                </InputAdornment>
              ),
            }}
            error={Boolean(touched.password && errors.password)}
            helperText={touched.password && errors.password}
          />
        </Stack>
        <LoadingButton
          fullWidth
          size="large"
          type="submit"
          variant="contained"
          // 当为false时停止加载动画
          loading={isSubmitting}
        >
          Login
        </LoadingButton>
      </Form>
    </FormikProvider>
  );
}

页面的逻辑很简单

这里如果对表单的代码不熟悉,可以看React表单组件的使用这篇文章

Mock数据

到此为止,表单的发送请求,以及接受请求之后的页面逻辑都已经处理完毕。我们需要验证一下,是否能够发起对后端的调用并且正常响应。

所以我们使用前端自己的mock数据。

关于各种mock工具,这里不做过多赘述,有兴趣的可以了解下。因为目前项目结构还很小,所以我们使用最简单的、并且不是太复杂的mock方法

mockjs

最终使用mockjs。mockjs我目前使用的不太爽的地方就是,官方文档给出的示例太少,而且没有一个流程很完成的示例。对于我这种后端开发来说太难受了

在src文件夹下新建mocks文件夹,所有的mock数据都在这里

mkdir mocks

在mocks文件夹下创建loginFormData.js文件,代表是api/loginForm的请求的mock数据,文件内容如下

const Mock = require("mockjs");
export default Mock.mock(
  "http://localhost:8081/badminton-community/login",
  "post",
  option => {
    // 这种情况需要重写mock
    return Mock.mock({
      code: 200,
      msg: "success",
    });
  }
);

注意:mockjs最坑的一点是拦截的方法类型是要小写的,而且我在官方文档上也没找到说明,这也太坑了吧

然后在api/loginForm.js中引入该文件即可

验证

所有工作都已经完成,目前我们验证手段是通过浏览器控制台打印,以及loading动画是否按照预期关闭这两种方式来验证这一流程是否符合我们的预期

npm run start

在表单中填写数据,点击LOGIN按钮,观察控制台输出 登录表单提交后浏览器控制台显示 Mock 请求结果

能够看到,流程符合预期。

后续

表单提交这一流程已经基本走通,代表着后续所有API请求,以及mock数据的拦截类似模式都可以打通了。

表单提交成功了之后,后续的逻辑应该是进入Dashboard,并路由,所有下一篇文章将进行路由相关工作的开发

资源


分享本文:

继续阅读本系列

React 应用入门

  1. React应用入门(一)搭建最简单的基本应用
  2. React应用入门(二)发送请求并Mock数据正在阅读

评论

欢迎提问、纠错和分享经验。发表评论需要登录 GitHub;中英文版本共享评论。

评论仅在正式网站开放。