Formik传入initialValues的对象键顺序无法保持如何解决
根因说明
Formik 的 enableReinitialize 触发逻辑依赖对 initialValues 的浅相等校验:只要前后两次传入的 initialValues 所有键对应的引用一致、键集合没有变化,就算键的顺序调整了,Formik 也会判定为数据未变更,不会更新内部的 values 状态,这就是你看到 before 打印顺序正确、after 打印顺序不变的核心原因。
可行解决方案(均满足保留对象格式、无需加随机值的要求)
方案1:给Formik组件绑定排序维度的key(最推荐,改造成本最低)
利用React原生的key属性特性:只要key值变化,组件会完全卸载重建,内部状态会直接使用最新的initialValues,不需要修改任何数据结构。
你只需要把排序的触发条件(比如排序字段、排序方向)拼接为key值绑定到Formik组件即可:
console.log('before', variationsByKey); return ( // 假设你当前的排序状态存储为 sortField(排序字段)、sortOrder(升/降序),直接拼接为key即可 <Formik key={`${sortField}-${sortOrder}`} enableReinitialize={true} initialValues={variationsByKey} {({ values }) => { console.log('after', values); // 原有业务逻辑 }} > )
方案2:主动调用resetForm更新状态
如果你不想重建Formik组件,可以用ref拿到Formik实例,在排序逻辑执行完成后主动调用resetForm传入新的排序后对象:
import { useRef } from 'react' const formikRef = useRef() // 排序触发函数 const handleSort = () => { // 原有排序逻辑得到新的variationsByKey const newVariationsByKey = 你的排序方法() // 主动更新Formik状态 formikRef.current.resetForm({ values: newVariationsByKey }) } // 组件内Formik绑定ref return ( <Formik innerRef={formikRef} enableReinitialize={true} initialValues={variationsByKey} {({ values }) => { // 原有业务逻辑 }} > )
方案3:添加可控的排序版本号触发重初始化
如果一定要依赖enableReinitialize的自动更新逻辑,可以在initialValues中新增一个业务无感知的_sortVersion字段,每次排序时版本号+1,让浅比较判定为数据变更,触发重初始化:
import { useState } from 'react' const [sortVersion, setSortVersion] = useState(0) // 排序触发逻辑 const handleSort = () => { // 原有排序逻辑 setSortVersion(prev => prev + 1) } // 构造带版本号的initialValues const initialValues = { ...variationsByKey, _sortVersion: sortVersion } // 遍历对象做渲染时过滤掉_version字段即可 return ( <Formik enableReinitialize={true} initialValues={initialValues} {({ values }) => { const renderValues = Object.fromEntries( Object.entries(values).filter(([key]) => key !== '_sortVersion') ) // 用renderValues做后续业务逻辑 }} > )
内容的提问来源于stack exchange,提问作者hamobi
相关产品推荐
相关产品推荐

