如何从OpenAPI规范或TypeScript类型自动生成React表单?
基于OpenAPI规范或TypeScript类型自动生成React表单的方案
当然可以实现,下面分两种路径给出具体解决方案:
一、基于FastAPI生成的OpenAPI规范(openapi.json)生成表单
1. 修复react-jsonschema-form的使用问题
你之前用react-jsonschema-form(简称RJSF)无法正常工作,大概率是没有正确将OpenAPI规范转换为兼容的JSON Schema,或者加载文件的方式有误:
- OpenAPI的Schema定义和标准JSON Schema有细微差异,需要用
openapi-schema-to-json-schema工具转换 - 加载
openapi.json时,不要直接读取本地文件路径,而是通过HTTP请求获取(比如FastAPI默认提供的/openapi.json接口)
示例代码:
import { Form } from '@rjsf/core'; import { convert } from 'openapi-schema-to-json-schema'; import { useEffect, useState } from 'react'; export function MessageForm() { const [schema, setSchema] = useState(null); useEffect(() => { // 从FastAPI获取openapi规范 fetch('/openapi.json') .then(res => res.json()) .then(openapi => { // 提取Message的schema并转换为JSON Schema const messageOpenApiSchema = openapi.components.schemas.Message; const jsonSchema = convert(messageOpenApiSchema); setSchema(jsonSchema); }); }, []); if (!schema) return <div>Loading...</div>; return <Form schema={schema} onSubmit={({ formData }) => console.log(formData)} />; }
2. 直接使用OpenAPI专用表单生成工具
还有更省心的工具,比如openapi-react-form,它可以直接解析OpenAPI规范并生成表单,无需手动转换Schema:
import { OpenApiForm } from 'openapi-react-form'; import { useEffect, useState } from 'react'; export function MessageForm() { const [openapi, setOpenapi] = useState(null); useEffect(() => { fetch('/openapi.json').then(res => res.json()).then(setOpenapi); }, []); if (!openapi) return <div>Loading...</div>; return ( <OpenApiForm openapi={openapi} schemaName="Message" onSubmit={values => console.log(values)} /> ); }
二、基于生成的TypeScript类型生成表单
如果你更倾向于用已有的TypeScript类型(比如自动生成的Message类型),可以通过类型转Schema的方式结合表单库实现:
1. 结合Zod + React Hook Form
先把TypeScript类型转换为Zod Schema,再用React Hook Form做表单渲染,类型完全同步:
第一步,用
ts-to-zod工具把TypeScript类型转成Zod Schema:
安装依赖:npm install ts-to-zod --save-dev
创建脚本generate-zod.ts:import { generateSchema } from 'ts-to-zod'; import fs from 'fs'; const tsCode = `export type Message = { role: string; content: string; };`; const { zodSchema } = generateSchema(tsCode, 'Message'); fs.writeFileSync('./src/schemas/message.zod.ts', zodSchema);运行脚本生成Zod Schema文件。
第二步,在React组件中使用:
import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { MessageSchema } from './schemas/message.zod'; type Message = z.infer<typeof MessageSchema>; export function MessageForm() { const { register, handleSubmit, formState: { errors } } = useForm<Message>({ resolver: zodResolver(MessageSchema) }); const onSubmit = (data: Message) => console.log(data); return ( <form onSubmit={handleSubmit(onSubmit)}> <div> <label>Role:</label> <input {...register('role')} /> {errors.role && <p>{errors.role.message}</p>} </div> <div> <label>Content:</label> <textarea {...register('content')} /> {errors.content && <p>{errors.content.message}</p>} </div> <button type="submit">Submit</button> </form> ); }
2. 使用Formily直接解析TypeScript类型
Formily支持直接从TypeScript类型生成表单,无需手动转换Schema:
安装依赖:npm install @formily/core @formily/react @formily/ts-transformer --save
示例代码:
import { createForm } from '@formily/core'; import { FormProvider, FormField, Input, Textarea } from '@formily/react'; import { transformSchema } from '@formily/ts-transformer'; // 从TypeScript类型生成表单Schema const formSchema = transformSchema<{ role: string; content: string; }>(); export function MessageForm() { const form = createForm({ initialValues: { role: '', content: '' }, onSubmit: (values) => console.log(values) }); return ( <FormProvider form={form}> <FormField schema={formSchema['role']} component={Input} /> <FormField schema={formSchema['content']} component={Textarea} /> <button type="submit" onClick={() => form.submit()}>Submit</button> </FormProvider> ); }
内容的提问来源于stack exchange,提问作者Bong Lo
相关产品推荐
相关产品推荐

