Token导航 LogoToken导航TokenDH.com
研究检索只读github未标认证来源可访问clear审计未展示

formily-migration-guide正式迁移指南

Agent Skill

formily-migration-guide 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

7,663

周安装

306

GitHub Stars

公开资料未说明

下载量

2,097
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:formily-migration-guide(正式迁移指南)
来源仓库:https://github.com/whinc/my-claude-plugins
仓库路径:skills/formily-migration-guide
安装命令:
npx skills add whinc/my-claude-plugins --skill "formily-migration-guide"
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

AgentSkills.tonpx skills
npx skills add whinc/my-claude-plugins --skill "formily-migration-guide"

简介

formily-migration-guide 提供从传统表单方案迁移至 Formily 的路径指引。

  • 适用于已有项目改造或技术栈升级时的平滑过渡支持。
  • 包含组件替换策略、状态迁移方法与兼容性处理建议。
  • 使用前需评估项目规模与依赖复杂度,分阶段实施降低风险。
  • 建议先在测试环境验证关键路径,确保数据流与 UI 表现一致。

SKILL.md

Formily Migration Guide

This skill provides comprehensive guidance for converting existing React forms to Formily. Focus on migration strategies, common patterns, and step-by-step conversion processes for different form libraries and vanilla React forms with TypeScript.

Migration Overview

Why Migrate to Formily?

  1. Better TypeScript support - Type-safe form management
  2. Schema-driven approach - Declarative form definitions
  3. Improved performance - Efficient reactivity and minimal re-renders
  4. Powerful validation - Built-in validation with custom rules
  5. Better developer experience - Less boilerplate, more maintainability

Migration Strategies

  1. Incremental migration - Convert forms one at a time
  2. Parallel development - Build new forms with Formily while maintaining existing ones
  3. Complete rewrite - Replace entire form system at once

From Vanilla React Forms

Before: Vanilla React Form

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

interface ContactForm {
  name: string
  email: string
  message: string
}

const VanillaContactForm: React.FC = () => {
  const [formData, setFormData] = useState<ContactForm>({
    name: '',
    email: '',
    message: ''
  })

  const [errors, setErrors] = useState<Partial<ContactForm>>({})
  const [isSubmitting, setIsSubmitting] = useState(false)

  const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
    const { name, value } = e.target
    setFormData(prev => ({ ...prev, [name]: value }))
    // Clear error when user starts typing
    if (errors[name as keyof ContactForm]) {
      setErrors(prev => ({ ...prev, [name]: '' }))
    }
  }

  const validateForm = (): boolean => {
    const newErrors: Partial<ContactForm> = {}

    if (!formData.name.trim()) {
      newErrors.name = 'Name is required'
    }

    if (!formData.email.trim()) {
      newErrors.email = 'Email is required'
    } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
      newErrors.email = 'Invalid email format'
    }

    if (!formData.message.trim()) {
      newErrors.message = 'Message is required'
    }

    setErrors(newErrors)
    return Object.keys(newErrors).length === 0
  }

  const handleSubmit = async (e: FormEvent) => {
    e.preventDefault()

    if (!validateForm()) {
      return
    }

    setIsSubmitting(true)

    try {
      // Submit form data
      await submitForm(formData)
      alert('Form submitted successfully!')
      setFormData({ name: '', email: '', message: '' })
    } catch (error) {
      console.error('Submission error:', error)
      alert('Submission failed. Please try again.')
    } finally {
      setIsSubmitting(false)
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Name:</label>
        <input
          type="text"
          name="name"
          value={formData.name}
          onChange={handleChange}
        />
        {errors.name && <span className="error">{errors.name}</span>}
      </div>

      <div>
        <label>Email:</label>
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
        />
        {errors.email && <span className="error">{errors.email}</span>}
      </div>

      <div>
        <label>Message:</label>
        <textarea
          name="message"
          value={formData.message}
          onChange={handleChange}
        />
        {errors.message && <span className="error">{errors.message}</span>}
      </div>

      <button type="submit" disabled={isSubmitting}>
        {isSubmitting ? 'Submitting...' : 'Submit'}
      </button>
    </form>
  )
}

After: Formily Version

import React from 'react'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'
import { Form, FormItem, Input, Button } from '@formily/antd'

interface ContactForm {
  name: string
  email: string
  message: string
}

const FormilyContactForm: React.FC = () => {
  const form = createForm<ContactForm>({
    initialValues: {
      name: '',
      email: '',
      message: ''
    },
    validateFirst: true
  })

  const schema = {
    type: 'object',
    properties: {
      name: {
        type: 'string',
        title: 'Name',
        required: true,
        'x-decorator': 'FormItem',
        'x-component': 'Input',
        'x-validator': [
          { required: true, message: 'Name is required' }
        ]
      },
      email: {
        type: 'string',
        title: 'Email',
        required: true,
        'x-decorator': 'FormItem',
        'x-component': 'Input',
        'x-validator': [
          { required: true, message: 'Email is required' },
          { format: 'email', message: 'Invalid email format' }
        ]
      },
      message: {
        type: 'string',
        title: 'Message',
        required: true,
        'x-decorator': 'FormItem',
        'x-component': 'Input.TextArea',
        'x-validator': [
          { required: true, message: 'Message is required' }
        ]
      }
    }
  }

  const SchemaField = createSchemaField({
    components: {
      Form,
      FormItem,
      Input,
      Button
    }
  })

  const handleSubmit = async () => {
    try {
      await form.validate()
      const values = form.values
      await submitForm(values)
      alert('Form submitted successfully!')
      form.reset()
    } catch (error) {
      console.error('Validation errors:', error)
    }
  }

  return (
    <FormProvider form={form}>
      <Form labelCol={6} wrapperCol={16}>
        <SchemaField schema={schema} />
        <FormItem wrapperCol={{ offset: 6, span: 16 }}>
          <Button type="primary" onClick={handleSubmit}>
            Submit
          </Button>
        </FormItem>
      </Form>
    </FormProvider>
  )
}

From Formik

Before: Formik Form

import React from 'react'
import { Formik, Form, Field, ErrorMessage } from 'formik'
import * as Yup from 'yup'

const FormikExample: React.FC = () => {
  const initialValues = {
    firstName: '',
    lastName: '',
    email: '',
    age: ''
  }

  const validationSchema = Yup.object({
    firstName: Yup.string().required('First name is required'),
    lastName: Yup.string().required('Last name is required'),
    email: Yup.string().email('Invalid email').required('Email is required'),
    age: Yup.number().min(18, 'Must be at least 18').required('Age is required')
  })

  const handleSubmit = (values: any, { setSubmitting }: any) => {
    submitForm(values)
    setSubmitting(false)
  }

  return (
    <Formik
      initialValues={initialValues}
      validationSchema={validationSchema}
      onSubmit={handleSubmit}
    >
      {({ isSubmitting }) => (
        <Form>
          <div>
            <label>First Name</label>
            <Field name="firstName" type="text" />
            <ErrorMessage name="firstName" component="div" />
          </div>

          <div>
            <label>Last Name</label>
            <Field name="lastName" type="text" />
            <ErrorMessage name="lastName" component="div" />
          </div>

          <div>
            <label>Email</label>
            <Field name="email" type="email" />
            <ErrorMessage name="email" component="div" />
          </div>

          <div>
            <label>Age</label>
            <Field name="age" type="number" />
            <ErrorMessage name="age" component="div" />
          </div>

          <button type="submit" disabled={isSubmitting}>
            Submit
          </button>
        </Form>
      )}
    </Formik>
  )
}

After: Formily Version

import React from 'react'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'
import { Form, FormItem, Input, InputNumber, Button } from '@formily/antd'

const FormilyFormikExample: React.FC = () => {
  const form = createForm({
    initialValues: {
      firstName: '',
      lastName: '',
      email: '',
      age: undefined
    }
  })

  const schema = {
    type: 'object',
    properties: {
      firstName: {
        type: 'string',
        title: 'First Name',
        required: true,
        'x-decorator': 'FormItem',
        'x-component': 'Input',
        'x-validator': [{ required: true, message: 'First name is required' }]
      },
      lastName: {
        type: 'string',
        title: 'Last Name',
        required: true,
        'x-decorator': 'FormItem',
        'x-component': 'Input',
        'x-validator': [{ required: true, message: 'Last name is required' }]
      },
      email: {
        type: 'string',
        title: 'Email',
        required: true,
        'x-decorator': 'FormItem',
        'x-component': 'Input',
        'x-validator': [
          { required: true, message: 'Email is required' },
          { format: 'email', message: 'Invalid email format' }
        ]
      },
      age: {
        type: 'number',
        title: 'Age',
        required: true,
        'x-decorator': 'FormItem',
        'x-component': 'InputNumber',
        'x-validator': [
          { required: true, message: 'Age is required' },
          { minimum: 18, message: 'Must be at least 18' }
        ]
      }
    }
  }

  const SchemaField = createSchemaField({
    components: {
      Form,
      FormItem,
      Input,
      InputNumber,
      Button
    }
  })

  const handleSubmit = async () => {
    try {
      await form.validate()
      const values = form.values
      await submitForm(values)
      form.reset()
    } catch (error) {
      console.error('Validation errors:', error)
    }
  }

  return (
    <FormProvider form={form}>
      <Form labelCol={6} wrapperCol={16}>
        <SchemaField schema={schema} />
        <FormItem wrapperCol={{ offset: 6, span: 16 }}>
          <Button type="primary" onClick={handleSubmit}>
            Submit
          </Button>
        </FormItem>
      </Form>
    </FormProvider>
  )
}

From React Hook Form

Before: React Hook Form

import React from 'react'
import { useForm, SubmitHandler } from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'
import * as Yup from 'yup'

interface FormData {
  username: string
  email: string
  password: string
  confirmPassword: string
}

const schema = Yup.object({
  username: Yup.string().required('Username is required'),
  email: Yup.string().email('Invalid email').required('Email is required'),
  password: Yup.string().min(8, 'Password must be at least 8 characters').required('Password is required'),
  confirmPassword: Yup.string().oneOf([Yup.ref('password')], 'Passwords must match').required('Confirm password is required')
})

const ReactHookFormExample: React.FC = () => {
  const { register, handleSubmit, formState: { errors }, watch } = useForm<FormData>({
    resolver: yupResolver(schema)
  })

  const watchedPassword = watch('password')

  const onSubmit: SubmitHandler<FormData> = (data) => {
    console.log(data)
    // Submit logic
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label>Username</label>
        <input {...register('username')} />
        {errors.username && <span>{errors.username.message}</span>}
      </div>

      <div>
        <label>Email</label>
        <input type="email" {...register('email')} />
        {errors.email && <span>{errors.email.message}</span>}
      </div>

      <div>
        <label>Password</label>
        <input type="password" {...register('password')} />
        {errors.password && <span>{errors.password.message}</span>}
      </div>

      <div>
        <label>Confirm Password</label>
        <input type="password" {...register('confirmPassword')} />
        {errors.confirmPassword && <span>{errors.confirmPassword.message}</span>}
      </div>

      <button type="submit">Submit</button>
    </form>
  )
}

After: Formily Version

import React from 'react'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'
import { Form, FormItem, Input, Button } from '@formily/antd'

interface FormData {
  username: string
  email: string
  password: string
  confirmPassword: string
}

const FormilyReactHookFormExample: React.FC = () => {
  const form = createForm<FormData>({
    initialValues: {
      username: '',
      email: '',
      password: '',
      confirmPassword: ''
    },
    effects() {
      // Custom validation for password match
      onFieldChange('confirmPassword', ['value'], (field) => {
        const password = form.values.password
        const confirmPassword = field.value

        if (confirmPassword && password !== confirmPassword) {
          field.errors = ['Passwords must match']
        } else {
          field.errors = []
        }
      })
    }
  })

  const schema = {
    type: 'object',
    properties: {
      username: {
        type: 'string',
        title: 'Username',
        required: true,
        'x-decorator': 'FormItem',
        'x-component': 'Input',
        'x-validator': [{ required: true, message: 'Username is required' }]
      },
      email: {
        type: 'string',
        title: 'Email',
        required: true,
        'x-decorator': 'FormItem',
        'x-component': 'Input',
        'x-validator': [
          { required: true, message: 'Email is required' },
          { format: 'email', message: 'Invalid email format' }
        ]
      },
      password: {
        type: 'string',
        title: 'Password',
        required: true,
        'x-decorator': 'FormItem',
        'x-component': 'Input.Password',
        'x-validator': [
          { required: true, message: 'Password is required' },
          { min: 8, message: 'Password must be at least 8 characters' }
        ]
      },
      confirmPassword: {
        type: 'string',
        title: 'Confirm Password',
        required: true,
        'x-decorator': 'FormItem',
        'x-component': 'Input.Password',
        'x-validator': [{ required: true, message: 'Please confirm your password' }]
      }
    }
  }

  const SchemaField = createSchemaField({
    components: {
      Form,
      FormItem,
      Input,
      Button
    }
  })

  const handleSubmit = async () => {
    try {
      await form.validate()
      const values = form.values
      console.log(values)
      // Submit logic
      form.reset()
    } catch (error) {
      console.error('Validation errors:', error)
    }
  }

  return (
    <FormProvider form={form}>
      <Form labelCol={6} wrapperCol={16}>
        <SchemaField schema={schema} />
        <FormItem wrapperCol={{ offset: 6, span: 16 }}>
          <Button type="primary" onClick={handleSubmit}>
            Submit
          </Button>
        </FormItem>
      </Form>
    </FormProvider>
  )
}

Migration Checklist

Pre-Migration Preparation

  1. Analyze existing forms

- Count total forms to migrate - Identify form complexity levels - Document validation logic - Note custom components used

  1. Set up Formily

- Install Formily packages - Configure TypeScript types - Set up Ant Design integration - Create basic form components

  1. Plan migration strategy

- Choose incremental vs complete rewrite - Define migration timeline - Assign team responsibilities - Set up testing strategy

Migration Steps

  1. Convert form structure

- Replace useState with createForm - Convert field definitions to schema - Update validation logic - Replace onChange handlers

  1. Update validation

- Convert Yup schemas to Formily validators - Implement custom validation rules - Set up async validation - Configure error messages

  1. Migrate components

- Replace Formik/React Hook Form components - Update Ant Design integration - Convert custom field components - Update form submission logic

  1. Test migration

- Unit test individual forms - Integration test form workflows - Test validation scenarios - Performance test large forms

Post-Migration

  1. Validation

- All forms render correctly - Validation works as expected - Form submission functions properly - TypeScript types are correct

  1. Optimization

- Remove unused dependencies - Optimize form performance - Update documentation - Train team on Formily

Common Migration Patterns

State Management Migration

// Before: Multiple useState hooks
const [name, setName] = useState('')
const [email, setEmail] = useState('')
const [errors, setErrors] = useState({})

// After: Single form instance
const form = createForm({
  initialValues: { name: '', email: '' }
})

Validation Migration

// Before: Manual validation
const validateForm = () => {
  const errors = {}
  if (!name) errors.name = 'Name is required'
  if (!email) errors.email = 'Email is required'
  setErrors(errors)
}

// After: Schema-based validation
const schema = {
  type: 'object',
  properties: {
    name: { type: 'string', required: true },
    email: { type: 'string', required: true, format: 'email' }
  }
}

Form Submission Migration

// Before: Manual submission handling
const handleSubmit = (e) => {
  e.preventDefault()
  if (validateForm()) {
    submitForm({ name, email })
  }
}

// After: Formily submission
const handleSubmit = async () => {
  await form.validate()
  submitForm(form.values)
}

Additional Resources

Templates

  • templates/migration-template.tsx - Reusable migration template
  • templates/validation-converter.ts - Validation logic converter utility

Reference Files

  • references/migration-comparison.md - Side-by-side comparison table
  • references/common-pitfalls.md - Migration pitfalls and solutions
  • references/validation-mapping.md - Validation rule mapping guide

Migration Tools

  • Use automated code migration scripts for simple forms
  • Create custom transformation utilities for complex forms
  • Implement gradual migration wrappers for mixed environments

Best Practices

  1. Start simple - Migrate basic forms first to learn the pattern
  2. Maintain type safety - Convert all forms to TypeScript
  3. Test thoroughly - Validate each migrated form matches original behavior
  4. Document changes - Keep track of migration decisions and patterns
  5. Iterate gradually - Improve forms after initial migration
  6. Monitor performance - Watch for performance issues in complex forms
  7. Train the team - Ensure all developers understand Formily patterns
  8. Plan for rollbacks - Keep original forms as backup during migration

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

28.92%
按下载量换算606

windsurf

21.78%
按下载量换算457

trae

18.01%
按下载量换算378

OpenCode

14.25%
按下载量换算299

Codex

7.7%
按下载量换算161

Antigravity

3.82%
按下载量换算80

安全审计

暂无安全审计结果可展示。

权限和风险

只读

该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills