preface

When we use the Fusion component library, we often use forms, which inevitably involves form verification. Of course, there are several solutions. The following is the usage of one of them: useImperative + forwardRef + Field. This kind of program I feel more troublesome, only as a reference.

The body of the

Bedding (hook function)

forwardRef

  • The forwardRef (verb) Reference) accepts a functional component and contains additional ref parameter, forwardRef can be realized in the parent component by component to give ref to child components, namely child components to obtain the parameters (ref), relatively simple case, we may not use, but for some reusable components you are on the right place. The parent needs the help of the forwardRef to get the parent ref object from the parent and then bind it to the parent’s target.

Ps: Ref usage scenarios: handling focus, text selection, or media control; Trigger the necessary animation; Integrate third-party DOM libraries.

Scenario 1: We want to get from the parent the instance object of the input box bound in the child.

Code:


import React, { Component, createRef, forwardRef } from 'react';
/ / child component
const SonInput = forward((props, ref) = > {
	<input type="text" ref={ ref} / >
})

/ / the parent component
class Father extends Component {
	constructor(props) {
    	super(props);
        this.ref = createRef();
    }
    componentDidMount() {
    	const { current } = this.ref;
        current.focus();
    }
    render() {
    	return (
        	<div>
            	<p>A sunny day</p>
                <SonInput ref={ this.ref} / >
            </div>)}}export default Father;
Copy the code

Scenario 2: Advanced components

If the subcomponent is wrapped by a forward, the react. forwardRef function also needs to use the react. forwardRef function. The react. forwardRef must also be wrapped around the high-order function factory.

import React, { Component, createRef } from 'react';

const SonInput = React.forwardRef((props, ref) = > 
	<input type="text" ref={ ref} / >
)

const FactoryHoc = (WrappedComponent) = > {
    const ConverRef = (props) = > {
    	const{ forwardRef, ... other } = props;return <WrappedComponent { . other } ref={forwardRef} />;
    }
    
    return React.forwardRef((props, ref) = > 
    <ConverRef {. props} forwardRef = {ref} /> ) 
    // Ref ={ref} is a reserved word, so we can pass ref like an attribute
}

const FactoryWithRef = FactoryHoc(SonInput);

/ / the parent component
class Father extends Component {
	constructor(props) {
    	super(props);
        this.ref = createRef();
    }
    
    componentDidMount() {
    	const { current } = this.ref;
        current.focus();
    }
    
    render() {
    	return (
            <div>
            	<p>It's sunny today</p>
                <FactoryWithRef ref = { this.ref} / >
            </div>)}}Copy the code

useImperactiveHandle

  • UseImperactiveHandle is a React hook for a custom REF object. It can be understood as “setRef”.

This allows us to customize the value of ref when we use ref

Here’s a simple example (from Jane’s Book)

function App() {
    const buttonRef = userRef(null);
    useEffect(() = > {
    	console.log(buttonRef.current);
    })
    return (
    	<div className="App">
            <Button2 ref={ buttonRef} >button</Button2>
            <button
            className="close"
            onClick={()= > {
            	buttonRef.current.x();
            }}
            >
            x
            </button>
        </div>)}const Button2 = React.forwardRef((props, ref) = > {
    const realButton = createRef(null);
    const setRef = useImperativeRef;
    setRef(ref, () = > {
    	return {
          x: () = > {
            realButton.current.remove();
          },
          realButton: realButton
        }
    })
    return <button ref={ realButton } { . props} / >;
})
Copy the code

implementation

UseImperativeHandle + forwardRef for form validation in fusion

// The parent component needs to control the presentation of the form
function ConfirmModel(record, refresh) {
    let form = null;
    const dialog = Dialog.show({
    	title: "".className: "".content: (<DialogContent ref={ ref= > form = ref } record={ record }/>)...onOk: () = > {
        	// Validate here and call the interface}})}/ / child component
import React, { forwardRef, useImperativeHandle, useState } from 'react';
import{Field, ... }from 'fusion'

function ConfirmModel(props, ref) {
    let field = Field.useField();
    useImperativeHandle(ref, () = > {
    	submit(successCb) {
        	field.validate((errors, values) = > {
            	if(errors) return; successCb(values); })}})}export default forwardRef(ConfirmModel);
Copy the code

Summary: The implementation of form validation is not recommended in real development, but it should be adapted to the current situation. We will learn how to implement this method in case we need to use it later in the React source code analysis. Stay tuned