React study notes - Simple form encapsulation using React Hooks

React study notes - Simple form encapsulation using React Hooks

foreword

After learning @我不是外星人's React Advanced Practice Guide, I learned the basic use of props, implicit injection of props, form nesting principles, etc. Use the knowledge of React Hooks learned to make simple changes to the demo given in the original text

I hope that through this practical demo, everyone can learn:

  1. basic use of props
  2. Learn to operate props.children, implicitly inject props
  3. Master the principle of form nesting (the reality is more complicated than this)

example

Component usage

/**
 *	组件使用
 *	./src/pages/App/App.js
 */
import React, {
    
     useRef } from 'react'
import Form from '../../components/Form/Form'
import FormItem from '../../components/FormItem/FormItem'
import Input from '../../components/Input/Input'

export default function App(){
    
    
	const form = useRef(null)
	const submit =()=>{
    
    
	  /* 表单提交 */
	  form.current.submitForm((formValue)=>{
    
    
	      console.log(formValue)
	  })
	}
	const reset = ()=>{
    
    
	  /* 表单重置 */
	  form.current.resetForm()
	}
	return (
	    <div>
	        <Form ref={
    
     form } >
	            <FormItem name="name" label="我是"  >
	                <Input/>
	            </FormItem>
	            <FormItem name="mes" label="我想对大家说"  >
	                <Input/>
	            </FormItem>
	            <input  placeholder="不需要的input" />
	            <Input/>
	        </Form>
	        <button className="searchbtn"  onClick={
    
     submit } >提交</button>
	        <button className="concellbtn" onClick={
    
     reset } >重置</button>
	    </div>
	)
}

Form component

import React, {
    
     useImperativeHandle, useState } from 'react'

const Form = React.forwardRef((props, ref)=>{
    
    
  const [formData,setFormData] = useState({
    
    })
  const submitForm = (cb) => {
    
    
    cb({
    
    ...formData})
  }
  const resetForm = () => {
    
    
    let formDataTemp = {
    
    ...formData}
    Object.keys(formDataTemp).forEach(item=>{
    
    
      formDataTemp[item] = ''
    })
    setFormData(formDataTemp)
  }
  const setValue = (name, value) => {
    
    
    setFormData({
    
    
      ...formData,
      [name]:value
    })
  }
  useImperativeHandle(ref,()=>({
    
    
    submitForm,
    resetForm
  }))
  const {
    
     children } = props
  const renderChildren = []
  React.Children.forEach(children, child => {
    
    
    if(child.type.displayName === 'formItem'){
    
    
      const {
    
     name } = child.props
      const Children = React.cloneElement(child ,{
    
    
        key: name,
        handleChange: setValue,
        value: formData[name] || ''
      },child.props.children)
      renderChildren.push(Children)
    }
  })
  return renderChildren
})

Form.displayName = 'form'

export default Form
  • To filter out elements other than FormItemthe element , how do you know FormItemif it is? Here is a way to teach you a way to bind a static property to a function component or class component to prove its identity, and then you can when props.childrentraversing On React elementthe typeattribute (class or function component itself), verify the identity. In this demo project, bind displayNamethe attribute to prove the identity of the component.
  • To clone FormItema node , mixinhandleChange the method that changes the form cell item and the value of the form into .valueprops

FormItem component

import React from 'react'

function FormItem(props) {
    
    
  const {
    
     handleChange, value, name, label, children} = props
  const onChange = (value) => {
    
    
    handleChange(name,value)
  }
  return (
    <div>
      <span>{
    
    label}:</span>
      {
    
    
        React.isValidElement(children) && children.type.displayName === 'input' ?
        React.cloneElement(children,{
    
    onChange, value}) : null
      }
    </div>
  )
}

FormItem.displayName = 'formItem'

export default FormItem
  • FormItemBe sure to bind displayNamethe property to allow <Form>the recognition<FormItem />
  • Declare onChangethe method , propsprovided to by <Input>, as the callback function for valuechanging .
  • FormItemFilter out other elements inputexcept .

Input component

import React from 'react'

function Input(props) {
    
    
  return (
    <input value={
    
    props.value} onChange={
    
    e=>props.onChange(e.target.value)}></input>
  )
}

Input.displayName = 'input'

export default Input
  • bind displayNameid input.
  • input DOMElement, bound onChangemethod , for passing value.

Guess you like

Origin blog.csdn.net/m0_52761633/article/details/123313155