React 学习笔记 - 使用React Hooks进行简单的表单封装

React 学习笔记 - 使用React Hooks进行简单的表单封装

前言

学完@我不是外星人的React进阶实践指南,了解了props的基本使用、隐式注入props、表单嵌套原理等。利用所学React Hooks知识对原文给出的demo进行了简单改动

希望通过这实践 demo 让大家学习到:

  1. props 基本使用
  2. 学会操作 props.children ,隐式注入 props
  3. 掌握表单嵌套原理(现实情况要比这个复杂)

示例

组件使用

/**
 *	组件使用
 *	./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组件

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
  • 要过滤掉除了 FormItem 元素之外的其他元素,那么怎么样知道它是不是FormItem,这里教大家一种方法,可以给函数组件或者类组件绑定静态属性来证明它的身份,然后在遍历 props.children 的时候就可以在 React elementtype 属性(类或函数组件本身)上,验证这个身份,在这个 demo 项目,给函数绑定的 displayName 属性,证明组件身份。
  • 要克隆 FormItem 节点,将改变表单单元项的方法 handleChange 和表单的值 value 混入 props 中。

FormItem 组件

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
  • FormItem一定要绑定 displayName 属性,用于让 <Form> 识别<FormItem />
  • 声明 onChange 方法,通过 props 提供给<Input>,作为改变 value 的回调函数。
  • FormItem过滤掉除了 input 以外的其他元素。

Input 组件

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
  • 绑定 displayName 标识input
  • input DOM 元素,绑定 onChange 方法,用于传递 value
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值