Definition: A higher-order component is a function that takes a component and returns a new component.

A component converts props to UI, and a higher-order component converts a component to another component. Examples include Redux’s Connect and Relay’s createFragmentContainer.

The basic use

Const foo = Cmp => props => {return (<div className="customCmp"> <p> Custom new component </p> <Cmp {... Function Child(props){return <div>Child {props. Name}</div>} const Foo = Foo (Child) // Child component Foo new component // It can also be chained using const Foo2 = Foo (Foo (Child)) // Multi-layer overlay // where page <Foo name="123" />Copy the code

Use in combination with decorator mode

To do this, you need to install plug-ins and configurations. NPM install -d @babel/plugin-proposal-decorators

// Decorators can only be used on classes. Question 1: What is the order of decorators? @foo @foo class child extends Components {render(){return <div>child</div>}} // use is decorated <Child />Copy the code

Note:

Do not use HOC in render methods. This isn’t just a performance issue – remounting a component causes a loss of state for that component and all its children. According to?

render() {
    // Each call to the Render function creates a new EnhancedComponent
    // EnhancedComponent1 ! == EnhancedComponent2
    const EnhancedComponent = enhance(MyComponent);
    // This will cause subtrees to be unmounted and remounted every time they are rendered!
    return <EnhancedComponent />;
}
Copy the code

Antd form example

React doesn’t have a two-way binding like Vue, so you might initially use the form input like this:

class FPage extends Component {
    constructor(props) {
        super(props)
        this.state = {
            name: ' '.password: ' '
        }
    }
    render(
        <div>
            <h3>State Indicates the self-maintenance mode</h3>
            <Input placeholder="name" value={name} onChange={ e= > {
                this.setState({name: e.target.value})
            }} />
            <Input placeholder="password" value={password} onChange={ e= > {
                this.setState({password: e.target.value})
            }} />
        </div>)}Copy the code

Use antD form.create () to decorate the implementation:

Form.create() :

  • GetFieldDecorator: Used for bidirectional binding with the form
  • GetFieldsValue: Gets the values of a set of input controls or, if no arguments are passed, the values of all components
  • GetFieldValue: Gets the value of an input control
  • ValidateFields validateFields
  • XXX other

2.x antd Controls wrapped with getFieldDecorator will automatically add value (or any other property specified by valuePropName) onChange (or any other property specified by trigger) and the data synchronization will be taken over by the Form

@Form.create()
class FPage2 extends Component {
    submit = () = > {
        console.log("submit", getFieldsValue(), getFieldValue("name"));
    };
    render(){
        console.log("props".this.props.form);
        const {getFieldDecorator} = this.props.form;
        return (
            <div>
                <h3>FormPage2</h3>
                <Form>
                    <Form.Item label="Name">
                        {
                            getFieldDecorator("name", {rules:[nameRules]})
                            (<Input placeholder="please input ur name" />)}</Form.Item>
                    // xxxx
                 
                </Form>
            </div>); }}Copy the code

The presentation component implements data collection, validation, and submission features that can be extended by higher-order components.

Take a look at the rough implementation of the form.create, getFieldDecorator

export default function kFormCreate(Cmp){
    return class extends Component {
        constructor(props){
            super(props)
            this.state = {}
            this.options = {}
        };
        handleChange(e){
            // Input change event
            let {name, value} = e.target;
            this.setState({[name]: value});
        };
        getFieldDecorator(){
            // Expand the Input tag
            this.options[field] = option;
            return InputCmp= > React.cloneElement(InputCmp, 
            { name: field, value: this.state[field] || "".onChange: this.handleChange // control change event handler
            });
        };
        getFieldsValue(){
            return{... this.state}; };getFieldValue(name){
            return this.state[name];
        };
        validateFields(){};
        render(){
            // Implement an extension to the method
            return 
            (
                <div className="cp">
                    <Cmp {. props} 
                        getFieldDecorator = {this.getFieldDecorator}
                        getFieldsValue = {this.getFieldsValue}
                        getFieldValue = {this.getFieldValue}
                        validateFields = {this.validateFields}
                    />
                </div>)}}}Copy the code

Antd source

Most Antd components are based on ant Financial’s react-component.rc-form component library

Rc-form parsing reference