如何在React类组件中使用Formik创建通用表单与字段封装?
适配方案
首先明确结论:不需要将整个组件层级改为函数组件。Hook的使用规则仅限制自身为函数组件/自定义Hook时的Hook调用位置,类组件渲染内部使用了Hook的子函数组件是完全合法的,你只需要调整你封装的通用表单层代码即可,改动量极小,不会影响现有大量业务代码。
首先排查现有代码错误
你写的PL_Form类组件中存在低级语法错误,可能是触发异常的直接原因:
// 你的原有错误写法 render() { let { children, onSubmit, initialValues, ...otherProps } = props; // 这里的props没有加this,类组件读取属性必须用this.props }
先修正该问题,如果依然报错,可选用以下任意一种适配方案:
方案1:仅重写PL_Form为函数组件(推荐,改动最小)
你的通用表单包装层逻辑非常简单,直接改为函数组件即可,现有所有调用它的业务类组件完全不需要修改:
import React from "react"; import { Formik, Form } from "formik"; import { object, func, elementType, any, bool, oneOfType } from "prop-types"; export default function PL_Form(props) { const { children, onSubmit, initialValues, ...otherProps } = props; return ( <Formik onSubmit={onSubmit} initialValues={initialValues} {...otherProps}> <Form> {children} </Form> </Formik> ); } PL_Form.propTypes = { initialValues: object.isRequired, onSubmit: func.isRequired }
方案2:保留PL_Form为类组件的适配方式
如果你坚持要保留PL_Form的类组件写法,可新增一层函数组件作为中间层包裹Formik,再在类组件中渲染该中间层:
import React, { Component } from "react"; import { Formik, Form } from "formik"; import { object, func, elementType, any, bool, oneOfType } from "prop-types"; // 新增中间层函数组件包裹Formik const FormikMiddleware = (props) => { const { children, onSubmit, initialValues, ...otherProps } = props; return ( <Formik onSubmit={onSubmit} initialValues={initialValues} {...otherProps}> <Form> {children} </Form> </Formik> ) } export default class PL_Form extends Component { static propTypes = { initialValues: object.isRequired, onSubmit: func.isRequired } render() { return <FormikMiddleware {...this.props} /> } }
以上两种方案均不需要修改现有业务类组件代码,你的MyField组件、业务调用代码都可以保持原有写法正常运行。
内容的提问来源于stack exchange,提问作者אשל בר
相关产品推荐
相关产品推荐

