react多级表单封装思路

72 阅读1分钟

多级表单的组件目录 image.png

总的组件useMutilForm。hooks的写法

import { ReactElement, useState } from 'react'

export function useMutilForm(steps: ReactElement[]) {
  //组件控制上一步下一步
  const [currntStepIndex, setCurrntStepIndex] = useState(0)
  function next() {
    // 判断边界值
    if (currntStepIndex === steps.length - 1) {
      return
    }
    setCurrntStepIndex(currntStepIndex + 1)
  }
  function prev() {
    // 判断边界值
    if (currntStepIndex === 0) {
      return
    }
    setCurrntStepIndex(currntStepIndex - 1)
  }

  return {
    currntStepIndex,
    setCurrntStepIndex,
    step: steps[currntStepIndex],
    next,
    prev,
    isFirstStep: currntStepIndex === 0,
    isLastStep: currntStepIndex === steps.length - 1,
  }
}

app.tsx

import './App.css'

import { useMutilForm } from './views/mutilForm/useMutilFrom'
import { AddressForm } from './views/mutilForm/addressForm'
import { UserForm } from './views/mutilForm/userForm'
import { AccountForm } from './views/mutilForm/accountForm'
import { FormEvent, useState } from 'react'

const FormData = {
  username: '',
  password: '',
  email: '',
  name: ' ',
  address: ' ',
  vx: '',
}
function App() {
  // 转成响应式数据
  const [data, setData] = useState(FormData)
  // 解构hooks的参数,通过数组形式去传组件
  const { step, prev, next, isFirstStep, isLastStep } = useMutilForm([
    <AddressForm {...data} changeValue={changeValue}></AddressForm>,
    <UserForm></UserForm>,
    <AccountForm></AccountForm>,
  ])
  // 改变state
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  function changeValue( value:any) {
    setData((prev)=>{
      return {...prev, ...value}
    })
  }
  // 提交表单
  function submit (e:FormEvent){
    // 阻止表单默认行为
    e.preventDefault()
    if(!isLastStep) return next()
    console.log('data', data)
  }
  return (
    <div className="border p-2">
      {step}
      {!isFirstStep && <button onClick={prev}>上一个</button>}

      <button onClick={submit}>{!isLastStep ? '下一个' : '完成'}</button>
    </div>
  )
}

export default App

其中一个子组件

import { FormWrapper } from './formWrapper'
type Address = { address: string; changeValue: (e: any) => void }
export function AddressForm({ address, changeValue }: Address) {
  return (
    // FormWrapper通用的组件容器
    <FormWrapper title="地址信息">
      <div className="flex">
        <label>地址:</label>
        <input
          type="text"
          autoFocus
          required
          value={address}
          onChange={(e) => changeValue({ address: e.target.value })}
        />
      </div>
    </FormWrapper>
  )
}

通用的组件容器

export function FormWrapper({ title,children }: { title:string,children: React.ReactNode }) {
  return (
    <div>
      <p>{title}</p>
      <div className="flex-col">{children}</div>
    </div>
  );
}

总结:

1.采用hooks组件的写法,把组件放在数组里面,解构拿到组件的变量和方法

const { step, prev, next, isFirstStep, isLastStep } = useMutilForm([
    <AddressForm {...data} changeValue={changeValue}></AddressForm>,
    <UserForm></UserForm>,
    <AccountForm></AccountForm>,
  ])

2.通用的容器提取成组件,通过children进行子组件展示

3.父组件拿到子组件的{key:value}进行解构重新赋值

setData((prev)=>{
      return {...prev, ...value}
    })