How to write event handling and data requests in React with TS?

function

In the Employee /QueryForm component, upgrade Input and Select to controlled components, and Button adds data request events to render a list of employee information.

implementation

Example Remove the interface file

We store all the data request types that interact with the back end under SRC /interface. For example, the state in the Employee /QueryForm is the format of the data request sent to the back end and can be isolated into an interface.

/* ** src/interface/employee.ts */

export interface EmployeeRequest {
  name: string;
  departmentId: number | undefinded;
}

// Single piece of data
interface EmployeeInfo {
  id: number;
  key: number;
  name: string;
  department: string;
  hiredate: string;
  level: string;
}

export type EmployeeResponse = EmployeeInfo[] | undefinded;
Copy the code

There are two benefits to defining an interface file:

  • It is beneficial to project maintenance, subsequent developers can be clear about the format type, and variables using the interface will have automatic prompt function.
  • Type checking, for unconsidered boundary cases,tsCan be comprehensive coverage, error reminder.

The event processing

Initialize the component state

import { EmployeeRequest } from ".. /.. /interface/employee";

// class QueryForm extends Component<{}, EmployeeRequest>
class QueryForm extends Component<{}, EmployeeRequest> {
  state = {
    name: "".departmentId: undefined}; }Copy the code

Bind value to Input and Select, add events

class QueryForm extends Component<{}, EmployeeRequest> {
  state = {
    name: "".departmentId: undefined};/* ** According to the official interface definition of 'Antd', the 'onChange' callback of 'Input' returns an event type ** onChange? : ((event: React.ChangeEvent
      
       ) => void) | undefined */
      
  handleNameChange = (e: React.FormEvent<HTMLInputElement>) = > {
    this.setState({ name: e.currentTarget.value });
  };

  /* ** onChange? : ((value: number, option: OptionsType | OptionData | OptionGroupData) => void) | undefined */
  handleDepartmentChange = (value: number) = > {
    this.setState({ departmentId: value });
  };

  render() {
    return (
      <>
        <Form layout="inline">
          <Form.Item>
            <Input
              placeholder="Name"
              style={{ width: 120 }}
              allowClear
              value={this.state.name}
              onChange={this.handleNameChange}
            />
          </Form.Item>
          <Form.Item>
            <Select
              placeholder="Department"
              style={{ width: 120 }}
              allowClear
              value={this.state.departmentId}
              onChange={this.handleDepartmentChange}
            >
              <Option value={1}>Technical department</Option>
              <Option value={2}>operations</Option>
              <Option value={3}>The Marketing Department</Option>
            </Select>
          </Form.Item>
          <Form.Item>
            <Button type="primary">The query</Button>
          </Form.Item>
        </Form>
      </>); }}Copy the code

Encapsulation Axios

Axios is a Promise-based HTTP library that can be used in browsers and Node.js.

/* ** src/utils/request.ts */

import originAxios from "axios";
import { message } from "antd";

// Create a custom instance and specify a request timeout of 20 seconds
const axios = originAxios.create({ timeout: 20000 });

// Add a response interceptor
axios.interceptors.response.use(
  function (response) {
    /* Return data format: successful Response: {"flag": 0, "data": ""} Unsuccessful Response: {"flag": 1, "MSG ": "error"} */
    if (response.data && response.data.flag === 1) {
      const errorMsg = response.data.msg;
      message.error(errorMsg);
      return Promise.reject(errorMsg);
    }
    return response.data;
  },
  function (error) {
    return Promise.reject(error); });// Encapsulate get & POST
export function get(url: string, data: any) {
  axios.get(url, { params: data });
}
export function post(url: string, data: any) {
  axios({ method: "post" }, url, data);
}
Copy the code

Because axios.post serializes JS objects to JSON format by default. So use axios({method: “post”}, url, data); , so that the back end can skip the JSON parsing step.

Define the request path

/* ** src/constans/urls.ts */
export const GET_EMPLOYEE_URL: string = "/api/employee/getEmployee.action";
Copy the code

mocking

When doing back-end separation development, we need to mock the request — proxy the request to the backend to the local mock Server.

Create a new mock folder under the root directory and start an API Server with mock as the root directory to provide us with mock services.

|--mock
    |--employee
        |--getEmployee.json
Copy the code
/* ** mock/employee/getEmployee.json */
{
  "flag": 0."data": [{"id": 1."key": 1."name": "Xiao Ming"."department": "Technical Department"."hiredate": "2019-07-01"."level": "Level 1"
    },
    {
      "id": 2."key": 2."name": "Small li"."department": "Product Department"."hiredate": "2017-07-01"."level": "Level 2"}]."msg": "Error"
}
Copy the code
/* ** package.json */
{
  "script": {..."server": "cd mock &$ hs -p 4000 -a localhost"}}Copy the code

Server script description:

  • Enter themockDirectory,
  • Start in the current directoryhttp-server, API port: 4000, service name:localhost

Then, open a new terminal to start the service:

Proxy the request locally:

When create-react-app starts, setupproxy.js is automatically called.

/* ** src/setupProxy.js */

const { createProxyMiddleware } = require("http-proxy-middleware");

module.exports = function (app) {
  app.use(
    createProxyMiddleware("/api/**/*.action", {
      target: "http://localhost:4000".pathRewrite(path) {
        return path.replace("/api"."/").replace(".action".".json"); }})); };Copy the code

In a development environment, requests are automatically brokered locally; In production, no code changes are required.

Send the request

Query events for the Button binding.

We fire the query request not only when the Button is clicked, but also when the page is initialized (componentDidMount).

import { get } from ".. /.. /utils/request";
import { GET_EMPLOYEE_URL } from ".. /.. /constans/urls";

class QueryForm extends Component<{}, EmployeeRequest> {
  handleSubmit = () = > {
    this.queryEmployee(this.state);
  };
  componentDidMount() {
    this.queryEmployee(this.state);
  }
  queryEmployee = (param: EmployeeRequest) = > {
    get(GET_EMPLOYEE_URL, param).then((response) = > {
      // TODO:Rendering logic
    });
  };
}
Copy the code

The request was sent successfully with mock data returned.

React & TS series

  • React & Typescript: Getting started with components
  • Headphones! TS + React Small project
  • Headphones! TS + React Small Project (02 Layout & Components)
  • Headphones! TS + React Small Project (03 Event Handling & Data Requests)
  • Headphones! TS + React Small project (04 List Rendering & Routing Configuration)
  • Headphones! TS + React Small Project (05 State Management Redux)