This section

Classroom goal

Using ant – Design

The official website

Common mode

download

npm install antd --save
Copy the code

Modify SRC/app.js to introduce antD button component.

import React, { Component } from 'react';
import Button from 'antd/es/button';
import './App.css';
import 'antd/dist/antd.css'

class App extends Component {
  render() {
    return (
      <div className="App">
        <Button type="primary">Button</Button>
      </div>); }}export default App;
Copy the code

Modify SRC/app.css to introduce ANTd /dist/ antD.css at the top of the file.

Advanced configuration

The configuration above is not very friendly and can cause a lot of problems in real development. For example, the loading style above loads the entire style

At this point we need to use react-app-rewired(a community solution for custom configuration of create-React-app). Introduce react-app-rewired and modify the startup configuration in package.json. Thanks to the new [email protected] version, you’ll also need to install customize-cra.

npm i react-app-rewired customize-cra babel-plugin-import --save-dev
Copy the code

Modify the package.json startup file

 "scripts": {
    "start": "react-app-rewired start"."build": "react-app-rewired build"."test": "react-app-rewired test"."eject": "react-app-rewired eject"
  },
Copy the code

Then create a config-overrides. Js file in the project root directory to modify the default configuration

Babel-plugin-import is a Babel plug-in for loading component code and styles on demand

const { override, fixBabelImports } = require('customize-cra');
module.exports = override(
    fixBabelImports('import', {
        libraryName: 'antd'.libraryDirectory: 'es'.style: 'css',}));Copy the code

Modify the App. Js

// import Button from 'antd/es/button';
// import 'antd/dist/antd.css'

import { Button } from 'antd';
Copy the code

run

npm start
Copy the code

Smart components vs. dumb components

The basics: The smart component (container component) is responsible for fetching data, and the dumb component (presentation component) is responsible for displaying information content according to props

Advantage:

  1. Separation of logic and content presentation
  2. High reusability
  3. High reusability
  4. Easy to test

In CommentList. Js

import React, {
    Component
} from 'react';

function Comment({ comment }) {
    console.log('render');
    return (
        <div>
            <p>{comment.id}</p>
            <p>{comment.content}</p>
            <p>{comment.author}</p>
        </div>)}class CommentList extends Component {
    constructor(props) {
        super(props);
        this.state = {
            comments: []}}componentDidMount() {
        // Get data
        setTimeout(() = > {
            this.setState({
                comments: [{id: 1.content: 'React is very good'.author: 'facebook'
                    },
                    {
                        id: 2.content: 'Vue is better than you'.author: 'Yu Yu Creek'}]})},1000);
    }

    render() {
        return (
            <div>
                {
                    this.state.comments.map((item, i) => (
                        <Comment comment={item} key={item.id} />))}</div>); }}export default CommentList;
Copy the code

A presentation component prints render twice, because there are two sets of data and render twice

I now do a rotation and update the data every second

// Start updating every 1 second
setInterval(() = > {
    this.setState({
        comments: [{id: 1.content: 'React is very good'.author: 'facebook'
            },
            {
                id: 2.content: 'Vue is better than you'.author: 'Yu Yu Creek'}]})},1000);
Copy the code

You’ll notice that every time the render is printed, the dumb component is re-rendered

Think: The data hasn’t changed, do I need to update it? Even though React is smart, it’s going to be a diff algorithm comparison between them, which is a performance drain

Solution 1: use shouldComponentUpdate

Extend COMMENT into a class component and define the following methods

shouldComponentUpdate(nextProps){
    if(nextProps.comment.id === this.props.comment.id){
        // return false indicates no update
        return false;
    }else{
        return true; }}Copy the code

Solution 2: Use React.PureComponent

React.purecomponent is similar to sholdComponentUpdate(). The difference is that the react. PureComponent does not implement shonldComponentUpdate(). Instead, the React.PureComponent implements this function in a shallow comparison of prop and state

If the object contains complex data structures, it is possible to produce incorrect alignment results because deep differences cannot be examined. Use React.PureComponent only if your props and state are simple

Modify CommentList. Js

render() {
    return (
        <div>
            {/* {
                    this.state.comments.map((item, i) => (
                        <Comment id={item.id} content={item.content} author={item.author} key={item.id} />)) * /}} {/ * or you can write *} {this.state.com ments. The map ((item, I) = > (<Comment {. item} key={item.id} />))}</div>
    );
}
Copy the code

Modify the Comment. Js

class Comment extends PureComponent{
    constructor(props) {
        super(props);
    }
    render() {
        console.log('render');
        return (
            <div>
                <p>{this.props.id}</p>
                <p>{this.props.content}</p>
                <p>{this.props.author}</p>
            </div>)}}Copy the code

Solution 3: Use React. Memo

React.memo is a higher-order component. It is very similar to the React.PureComponent, but it applies to function components, not class components.

const Comment = React.memo(({id,content,author}) = >{
    return (
        <div>
            <p>{id}</p>
            <p>{content}</p>
            <p>{author}</p>
        </div>)})Copy the code

Modify CommentList. Js

class CommentList extends Component{
    render() {
        return (
            <div>
                {
                    this.state.comments.map((item, i) => (
                        <Comment id={item.id} content={item.content} author={item.author} key={item.id} />))}</div>); }}Copy the code

Component composition rather than inheritance

The official quote is this:

React has a very powerful combination mode. We recommend using composition rather than inheritance to achieve code reuse between components.

/components/Compond.js

import React, { Component } from 'react';
import {
    Button
} from "antd";
function Dialog(props) {
    return (
        <div style={{ border: `3px solidThe ${props.color| | 'blue` '}}} >{/* Equivalent to: vue anonymous socket */} {props. Children} {/* named socket */}<div>
                {props.btn}
            </div>
        </div>)}// Pass any component as a child
function WelcomeDialog() {
    const confirmBtn = <Button type='primary' onClick={()= >{alert('react really good ')}}> Confirm</Button>
          return (
              <Dialog color='green' btn={confirmBtn}>
                  <h3>welcome</h3>
                  <p>welcome</p>
              </Dialog>)}class Compound extends Component {
    render() {
        return (
            <div>
                <WelcomeDialog />
            </div>); }}export default Compound;
Copy the code

High order component

The purpose of component design is to ensure the simplicity of component function

// Higher-order componentsA function that receives a component and returns a new component Comment is like: I give you a Saiyan, you give me a super Saiyan// Higher order functionDefinition: receive arguments that are functions or return values that are common to functions: array traversal related methods, timers,Promise/ Advanced component role: to achieve a more powerful, dynamic functionCopy the code

Higher-order Component (HOC) is an advanced technique used in React to reuse component logic. HOC itself is not part of the React API; it is a design pattern based on the composite features of React.

Specifically, a higher-order component is a function that takes a component and returns a new component

/components/Hoc.js

const HightOrderCom = (Comp) = > {
    // Returns a new component
   const NewComponent =  function (props) {
    	return <Comp name='react' content='Use of Advanced Components' {. props} ></Comp>
    }
   return NewComponent;
}

Copy the code

The HightOrderCom component above, in effect, proxies Comp by passing in the name and content parameters

import React, { Component } from 'react'

function MyNormalCom(props) {
  return (
    <div>
      <p>Class name :{props. Name}</p>
      <h3>{props. Content}</h3>
    </div>)}// Advanced components
const HighOrderCom = (Comp) = > {
  return (props) = >{
    return <Comp name='react' content='Use of higher-order components' {. props} ></Comp>}}export default HighOrderCom(MyNormalCom);
Copy the code

Overrides the internal lifecycle of higher-order components

const HightOrderCom = (Comp) = > {
    // Returns a new component
    return class extends Component {
        constructor(props) {
            super(props)
        }
        componentDidMount(){
            console.log('Make an Ajax request');

        }
        render() {
            return (
                <Comp name='react' content='Use of Advanced Components' {. this.props} ></Comp>); }}}Copy the code

Higher-order component chain calls

// A higher-order component that prints logs
const WithLog = (Comp) = >{
    console.log(Comp.name + 'Rendered');
    const MyComponent =  function(props) {
        return <Comp {. props} ></Comp>
    }
    return MyComponent;
}
Copy the code

Call:

const HOC =  HightOrderCom(WithLog(WithLog(MyNormalCom)));
Copy the code

High order component decorator writing

While the chain-writing is a pain in the neck and the logic is convoluted, ES7 has an excellent syntax for dealing with this problem: decorator

cnpm install --save-dev babel-plugin-transform-decorators-legacy @babel/plugin-proposal-decorators
Copy the code

Configuration modification:

const {
    override,
    fixBabelImports, // Load configuration functions on demand
    addBabelPlugins // Babel plug-in configuration function
} = require('customize-cra');
module.exports = override(
    fixBabelImports('import', {
        libraryName: 'antd',
        libraryDirectory: 'es',
        style: 'css',
    }),
    addBabelPlugins( // Support decorators
        [
            '@babel/plugin-proposal-decorators',
            {
                legacy: true}]));Copy the code
const HightOrderCom = (Comp) = > {
    // Returns a new component
    return class extends Component {
        constructor(props) {
            super(props)
        }
        componentDidMount() {
            console.log('Make an Ajax request');

        }
        render() {
            return (
                <Comp name='react' content='Use of Advanced Components' {. this.props} ></Comp>); }}}// A higher-order component that prints logs
const WithLog = (Comp) = > {
    console.log(Comp.name + 'Rendered');
    const MyComponent = function (props) {
        return <Comp {. props} ></Comp>
    }
    return MyComponent;
}
@withLog
@HighOrderCom
@withLog
class Hoc extends Component {
    constructor(props){
        super(props);
    }
    render() {
        return (
            <div>
                <p>Class name :{this.props. Name}</p>
                <h3>{this.props. Content}</h3>
            </div>); }}export default Hoc;
Copy the code

Resolve red warnings in vscode

Find the gear button in the lower left corner of the editor and click the button to find the Settings. You will be presented with two interfaces: 1. Enter experimental decorators on the edit screen and check the box shown

Advanced component applications

Access control

The conditional rendering feature of higher-order components can be used to control page permissions

/components/HocApp.js

import React, { Component } from 'react'
// Permission control
// Technology that doesn't talk about the scene is playing hooligan
export const withAdminAuth = (role) = > (WrappedComp) = > {
  return class extends Component {
    constructor(props) {
      super(props);
      this.state = {
        isAdmin: false}}componentDidMount() {
      setTimeout(() = > {
        this.setState({
          isAdmin: role === 'Admin'})},1000);
    }

    render() {
      if (this.state.isAdmin) {
        return (
          <WrappedComp {. this.props} ></WrappedComp>
        );
      } else {
        return (
          <div>You do not have permission to view this page, please contact the administrator</div>)}}}}Copy the code

Then there are two pages:

/components/PageA.js

import React, { Component } from 'react'
import { withAdminAuth } from "./HocApp";
class PageA extends Component {
  componentDidMount() {
    setTimeout(() = > {
      this.setState({
        isAdmin: true})},1000);
  }
  render() {
    return (
      <div>
        <h2>I'm page A</h2>
      </div>)}}export default withAdminAuth('Admin')(PageA)
Copy the code

/components/PageB.js

import React, { Component } from 'react'
import { withAdminAuth } from "./HocApp";
class PageB extends Component {
  render() {
    return (
      <div>
        <h2>I'm page B</h2>
      </div>)}}export default withAdminAuth()(PageB);

Copy the code

Page A can be accessed, but page B cannot be accessed

Page reuse

Component Communication Context

Context provides a way to pass data across the component tree without manually adding props for each layer of components.

In a typical React application, data is passed top-down (from parent to child) through the props properties, but this is extremely cumbersome for certain types of properties (e.g. locale preferences, UI themes) that are required by many components in the application. Context provides a way to share such values between components without explicitly passing props layer by layer through the component tree.

When to use Context

Context is designed to share global data, such as the currently authenticated user, topic, and so on. Here’s an example:

import React, { Component } from 'react';
// Context allows us to go through each component and push values deeper into the component tree
// Create a ThemeContext with the default value light
const ThemeContext  = React.createContext('lighter');

class ThemeButton extends Component {
    // Specify contextType to read the current theme context.
    // React will find the nearest theme Provider and use its value.
    // In this case, the current theme value is "dark".
    Static contextType = ThemeContext; static contextType = ThemeContext;
    render() {
        return (
            // <button type={this.context}></button>
            <ThemeContext.Consumer>{/* 2. Render value based on function equivalent to this.context */} {value =><button theme={value.theme}>{value.name}</button>
                }
            </ThemeContext.Consumer>); }}function Toolbar(props) {
    // The Toolbar component accepts an additional "theme" property, which is passed to the ThemedButton component.
    // If every single button in your application needs to know the theme value, this would be a hassle,
    // Because this value must be passed layer by layer to all components.
    return (
        <div>
            <ThemeButton></ThemeButton>
        </div>)}// The data passed
const store = {
    theme:'dark'.name:'button'
}
class ContextSimple extends Component {
    // Use the Provider to push the current value='dark' into the component tree so that any component can read the value, no matter how deep
    render() {
        return (
            <div>
                <ThemeContext.Provider value={store}>
                    <Toolbar></Toolbar>
                </ThemeContext.Provider>
            </div>); }}export default ContextSimple;
Copy the code

High order component decorator writing

import React, { Component } from 'react';
const ThemeContext = React.createContext('lighter');
const withConsumer = Comp= > {
    return class extends Component {
        constructor(props) {
            super(props);
            
        }
        render() {
            return (
                <ThemeContext.Consumer>
                    {
                        value => <Comp {. this.props} value={value}></Comp>
                    }
                </ThemeContext.Consumer>
            );
        }
    }
}
@withConsumer
class ThemeButton extends Component {
    constructor(props) {
        super(props);
        
    }
    render() {
        return (
            <button theme={this.props.value.theme}>{this.props.value.name}</button>); }}function Toolbar(props) {
    return (
        <div>
            <ThemeButton></ThemeButton>
        </div>)}// The data passed
const store = {
    theme: 'dark'.name: 'button'
}

const withProvider = Comp= > {
    return function (props) {
        return (
            <ThemeContext.Provider value={store}>
                <Comp {. props} / >
            </ThemeContext.Provider>
        )
    }
}
@withProvider
class ContextSimple extends Component {
    render() {
        return (
            <div>
                <Toolbar></Toolbar>
            </div>); }}export default ContextSimple;
Copy the code

Encapsulate antD’s form form

Go to antD’s official website

import React from 'react'
import { Form, Icon, Input, Button } from 'antd';

function hasErrors(fieldsError) {
    return Object.keys(fieldsError).some(field= > fieldsError[field]);
}

class HorizontalLoginForm extends React.Component {
    componentDidMount() {
        // To disabled submit button at the beginning.
        this.props.form.validateFields();
    }
    handleSubmit = e= > {
        e.preventDefault();
        this.props.form.validateFields((err, values) = > {
            if(! err) {console.log('Received values of form: ', values); }}); };render() {
    const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form;

    // Only show error after a field is touched.
    const usernameError = isFieldTouched('username') && getFieldError('username');
    const passwordError = isFieldTouched('password') && getFieldError('password');
    return (
        <Form layout="inline" onSubmit={this.handleSubmit}>
            <Form.Item validateStatus={usernameError ? 'error' :"'}help={usernameError| | '} >
                {getFieldDecorator('username', {
                    rules: [{ required: true, message: 'Please input your username!' }],
                })(
                    <Input
                        prefix={<Icon type="user" style={{ color: 'rgba(0.0.0.25.) '}} / >}
                        placeholder="Username"
                        />,
                )}
            </Form.Item>
            <Form.Item validateStatus={passwordError ? 'error' :"'}help={passwordError| | '} >
                {getFieldDecorator('password', {
                    rules: [{ required: true, message: 'Please input your Password!' }],
                })(
                    <Input
                        prefix={<Icon type="lock" style={{ color: 'rgba(0.0.0.25.) '}} / >}
                        type="password"
                        placeholder="Password"
                        />,
                )}
            </Form.Item>
            <Form.Item>
                <Button type="primary" htmlType="submit" disabled={hasErrors(getFieldsError())}>
                    Log in
                </Button>
            </Form.Item>
        </Form>); }}const WrappedHorizontalLoginForm = Form.create({ name: 'horizontal_login' })(HorizontalLoginForm);

ReactDOM.render(<WrappedHorizontalLoginForm />, mountNode);
Copy the code

Component function analysis

  • Each input box is triggered to perform a non-null check with an error
  • Verify the form items when submitting the form. If the verification succeeds, login will be prompted; otherwise, verification failure will be prompted
  • Form items have front ICONS

Component Encapsulation

  1. You need a higher-order function HOC,MFormCreate, mainly responsible for packaging user forms and increasing data management ability; It needs to extend four features:getFieldDecorator, getFieldsError, getFieldError, isFieldTouched. Gets the field wrapper methodgetFieldDecoratorThe return value of is an advanced function that takes an Input component as an argument and returns a new component. This is to turn an ordinary form item into a form item with extended functionality (for example, adding validation rules for that item).
  2. The FormItem component is responsible for displaying checksum and error information. It needs to save two properties, the checksum status and error information. The error information is empty when the checksum is passed
  3. Input component, display component, add Input box front icon
  4. Export the MForm component decorated with MFormCreate, which is responsible for style layout and submission control

Component packaging Steps

  1. Complete a basic component MForm, page display
  2. Write a higher-order component MFormCreate to extend MForm, so that THE MForm component has the ability to manage data.
    1. Save field options set this.options = {}; We don’t need to save state here because we don’t want the field options to change and the component to be re-rendered
    2. Save the value of each field this.state = {}
    3. Define the method getFieldDecorator()(), passing the configuration item as the first argument and the Input component as the second argument; The first parameter includes the current verification item and verification rule'username',{rules:[require:true,message:' enter username']}
    4. In MFormCreate, clone an Input component and define the onChange event for the Input. First, we need to clone the existing JSX and modify its properties. It is not allowed to modify the properties directly. Here the onChange event is defined at a higher level to control the value of the element so that there is no communication back and forth between components when they change. The data changes are left to the container component, and the lower-level component is only responsible for presentation.
  3. Added the submission verification function
  4. Add FormItem component to perform real-time verification and prompt error message after the FormItem is triggered

MForm.js

import React, { Component } from 'react';

class MForm extends Component {
    render() {
        return (
            <div>
                <input type="text" />
                <input type="password"/>
                <input type="submit" value='login'/>
            </div>); }}export default MForm;
Copy the code

Extend the MForm component with the higher-order component MFormCreate; Display validation error information through the FormItem component

import React, { Component } from 'react';
// Wrap the user form, add data management capability and validation function
const MFormCreate = function (Comp) {
    return class extends Component {
        constructor(props) {
            super(props);
            this.state = {};// Save the values of each field
            this.options = {}; // Save the field option setting does not want it to change to let the component render

        }
        // Process the form entry event
        handlerChange = (e) = > {
            const { name, value } = e.target;
            console.log(name, value);
            this.setState({
                [name]:value
            },() = >{
                // The user has completed the input in the page
            })

        }
        getFieldDecorator = (fieldName, option) = > {
            // Set the field option configuration
            this.options[fieldName] = option;

            return (InputComp) = > {
                return <div>{react. cloneElement(InputComp, {name: fieldName, // control name: value); This. The state (fieldName) | | ', / / control value onChange: enclosing handlerChange, / / change event handling})}</div>}}render() {
            return (
                <Comp {. this.props} name='Joe' getFieldDecorator={this.getFieldDecorator} />
            )
        }

}
}
@MFormCreate
class MForm extends Component {

    render() {
        const { getFieldDecorator } = this.props;

        return (
            <div>{getFieldDecorator('username', {rules: [{required: true, message: "username is required"}]})(<input type='text' />)} {getFieldDecorator(' PWD ', {rules: [{required: true, message: "Password required"}]})(<input type='password' />)}<input type="submit" value='login' />
            </div>); }}export default MForm;
Copy the code

Verification of form entry after completion

MFormCreate higher-order component

const MFormCreate = function (Comp) {
    return class extends Component {
        constructor(props) {
            super(props);
            this.state = {};// Save the values of each field
            this.options = {}; // Save the field option Settings

        }
        // Process the form entry event
        handlerChange = (e) = > {
            const { name, value } = e.target;
            // console.log(name, value);
            this.setState({
                [name]: value
            }, () = > {
                // The user has entered the form in the page
                this.validateField(name)
            })

        }
        // Verify the form entry
        validateField = (fieldName) = > {
            const { rules } = this.options[fieldName];
            const ret = rules.some(rule= > {
                if (rule.required) {
                    // If the input field value is null
                    if (!this.state[fieldName]) {
                        this.setState({
                            [fieldName + 'Message']: rule.message
                        })
                        return true; // Verification failed, return true}}})// console.log(ret);
            if(! ret) {this.setState({
                    [fieldName + 'Message'] :' '})}return! ret;// Verify success returns false
        }
        getFieldDecorator = (fieldName, option) = > {
            // Set the field option configuration
            this.options[fieldName] = option;

            return (InputComp) = > {
                return <div>{/ *... * /} {/ * validation shows * /} {this. The state [fieldName + "Message"] && (<p style={{ color: 'red' }}>{this.state[fieldName + 'Message']}</p>)}</div>}}render() {
            return (
                <Comp {. this.props} name='Joe' getFieldDecorator={this.getFieldDecorator} />)}}}Copy the code

Click submit button to verify

const MFormCreate = function (Comp) {
    return class extends Component {
        constructor(props) {
            super(props);
            this.state = {};// Save the values of each field
            this.options = {}; // Save the field option Settings

        }
        // Process the form entry event
        handlerChange = (e) = > {
            const { name, value } = e.target;
            // console.log(name, value);
            this.setState({
                [name]: value
            }, () = > {
                // The user has entered the form in the page
                this.validateField(name)
            })

        }
        // Verify the form entry
        validateField = (fieldName) = > {
            const { rules } = this.options[fieldName];
            const ret = rules.some(rule= > {
                if (rule.required) {
                    // If the input field value is null
                    if (!this.state[fieldName]) {
                        this.setState({
                            [fieldName + 'Message']: rule.message
                        })
                        return true; // Verification failed, return true}}})// console.log(ret);
            if(! ret) {this.setState({
                    [fieldName + 'Message'] :' '})}return! ret;// Verify success returns false
        }
        validate = (cb) = > {            
            const rets = Object.keys(this.options).map(fieldName= > this.validateField(fieldName))
            // If all the values in the array are true, the verification succeeds
            const ret = rets.every(v= >v===true);
            cb(ret);
        }
        getFieldDecorator = (fieldName, option) = > {
            // Set the field option configuration
            this.options[fieldName] = option;

            return (InputComp) = > {
                return <div>{react. cloneElement(InputComp, {name: fieldName, // control name: value); This. The state (fieldName) | | ', / / control value onChange: This handlerChange, / / change event handling})} {this. The state [fieldName + "Message"] && (<p style={{ color: 'red' }}>{this.state[fieldName + 'Message']}</p>)}</div>}}render() {
            return (
                <Comp {. this.props} name='Joe' getFieldDecorator={this.getFieldDecorator} validate={this.validate} />
            )
        }

    }
}


@MFormCreate
class MForm extends Component {
    constructor(props) {
        super(props);
    }
    handlerSubmit = () = > {
        // If isValid is true, the verification succeeds; if flase is flase, the verification fails
        this.props.validate((isValid) = > {
            console.log(isValid);
            if(isValid){
                alert('Verification successful');
            }else{
                alert('Verification failed'); }})}render() {
        const { getFieldDecorator } = this.props;
        return (
            <div>{/ *... * /}<input type="submit" value='login' onClick={this.handlerSubmit} />
            </div>); }}Copy the code

Finally, wrap the FormItem and Input components

import React, { Component } from 'react';
import { Icon } from 'antd'

// Wrap the user form, add data management capability and validation function
const MFormCreate = function (Comp) {
    return class extends Component {
        constructor(props) {
            super(props);
            this.state = {};// Save the values of each field
            this.options = {}; // Save the field option Settings

        }
        // Process the form entry event
        handlerChange = (e) = > {
            const { name, value } = e.target;
            // console.log(name, value);
            this.setState({
                [name]: value
            }, () = > {
                // The user has entered the form in the page
                this.validateField(name)
            })

        }
        // Verify the form entry
        validateField = (fieldName) = > {
            const { rules } = this.options[fieldName];
            const ret = rules.some(rule= > {
                if (rule.required) {
                    // If the input field value is null
                    if (!this.state[fieldName]) {
                        this.setState({
                            [fieldName + 'Message']: rule.message
                        })
                        return true; // Verification failed, return true}}})// console.log(ret);
            if(! ret) {this.setState({
                    [fieldName + 'Message'] :' '})}return! ret;// Verify success returns false
        }
        validate = (cb) = > {
            const rets = Object.keys(this.options).map(fieldName= > this.validateField(fieldName))
            // If all the values in the array are true, the verification succeeds
            const ret = rets.every(v= > v === true);
            cb(ret);
        }
        getFieldDecorator = (fieldName, option) = > {
            // Set the field option configuration
            this.options[fieldName] = option;

            return (InputComp) = > {
                return <div>{react. cloneElement(InputComp, {name: fieldName, // control name: value); Enclosing the state (fieldName) | | ', / / control value onChange: enclosing handlerChange, / / change event handling an onFocus: enclosing handlerFocus})}</div>}}// Control gets the focus event
        handlerFocus = (e) = > {
            const field = e.target.name;
            console.log(field);
            
            this.setState({
                [field + 'Focus'] :true})}// Determine whether the control is clicked
        isFieldTouched = field= >!!!!!this.state[field + 'Focus']

        // Get control error information
        getFieldError = field= > this.state[field + "Message"];
        render() {
            return (
                <Comp
                    {. this.props}
                    getFieldDecorator={this.getFieldDecorator}
                    validate={this.validate}
                    isFieldTouched={this.isFieldTouched}
                    getFieldError={this.getFieldError}
                />)}}}// Create the FormItem component
class FormItem extends Component {
    render() {
        return (
            <div className='formItem'>
                {this.props.children}
                {
                   this.props.validateStatus === 'error' && (<p style={ { color: 'red'}} >{ this.props.help}</p>)}</div>); }}// Create the Input component
class Input extends Component {
    render() {
        return (
            <div>{/* prefix icon */} {this.props. Prefix}<input {. this.props} / >
            </div>
        );
    }
}


@MFormCreate
class MForm extends Component {
    constructor(props) {
        super(props);
    }
    handlerSubmit = () = > {
        // If isValid is true, the verification succeeds; if flase is flase, the verification fails
        this.props.validate((isValid) = > {
            console.log(isValid);
            if (isValid) {
                alert('Verification successful');
            } else {
                alert('Verification failed'); }})}render() {
        const { getFieldDecorator, isFieldTouched, getFieldError } = this.props;
        const usernameError = isFieldTouched('username') && getFieldError('username');
        const pwdError = isFieldTouched('pwd') && getFieldError('pwd');
        
        return (
            <div>
                <FormItem validateStatus={usernameError ? 'error' :"'}help={usernameError| | '} >{getFieldDecorator('username', {rules: [{required: true, message: "username is required ",}]})(<Input type='text' prefix={<Icon type='user' />}} / >)</FormItem>
                <FormItem validateStatus={pwdError ? 'error' :"'}help={pwdError| | '} >{getFieldDecorator(' PWD ', {rules: [{required: true, message: "Password is required"}]})(<Input type='password' prefix={<Icon type='lock' />}} / >)</FormItem>
                <input type="submit" value='login' onClick={this.handlerSubmit} />
            </div>); }}export default MForm;

Copy the code

conclusion

  • The React component is a top-down extension, passing the ability to extend from top to bottom, and the Input component can call the passed value at the appropriate time.
  • React components are developed according to the following principle: the logic control is promoted to the upper layer, and the lower-level components are as dumb as possible, and do not touch the business logic.