We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
codesandbox使用有问题,换了一个复现的链接,看这里 https://stackblitz.com/edit/react-zcgdmp5t-qzgwbljr?file=demo.tsx,index.tsx
程序首先给数组实例设置了长度为4的默认值,并且给每个字段实例设置了 disabled = true
复现操作:一直删除0号位置的元素
逐一删除0号位置的元素,删除第二个时禁用状态保留,观察form.fields,array.0.input的字段实例不应该被重新生成。
逐一删除0号位置的元素,删除第二个时会发现禁用状态丢失了,原本应该禁用的组件变成了非禁用的状态,观察form.fields,会发现array.0.input的字段实例被重新生成了。
@formily/[email protected]
debug了一下@formily/core的源码,发现了一个会造成该现象的原因:
数组字段每次执行remove时会调用 spliceArrayState (packages/core/src/shared/internals.ts)
batch(() => { each(fields, (field, identifier) => { if (isArrayChildren(identifier)) { if (isAfterNode(identifier)) { const newIdentifier = moveIndex(identifier) fieldPatches.push({ type: 'update', address: newIdentifier, oldAddress: identifier, payload: field, }) } if (isInsertNode(identifier) || isDeleteNode(identifier)) { fieldPatches.push({ type: 'remove', address: identifier }) } } }) patchFieldStates(fields, fieldPatches) })
这个函数的作用就是在有元素删除时,重新更新每个数组子元素的在form.fields中的path和对应的实例
问题就出在 each(fields, (field, xxx 对对象类型的key的遍历顺序上,
当第一次执行remove时,遍历的顺序是 array.0.input => array.1.input => array.2.input => array.3.input => array.4.input 没有问题
当第二次执行remove时,遍历的顺序是 array.1.input => array.2.input => array.3.input => array.0.input 此时就会出现问题
array.1.input最先被处理,也就是先重新生成了 array.0.input 和其对应的实例,但是在最后一步遍历 array.0.input 时,命中了fieldPatches.push({ type: 'remove', address: identifier })的逻辑,
刚生成的0号位置的新的实例被错误的删除了!!
我尝试修改 fieldPatches.push({ type: 'remove', address: identifier }) 为 fieldPatches.unshift({ type: 'remove', address: identifier }) 可以解决这个问题
逻辑就是让删除操作先执行,变更的操作后执行来消除这个影响。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
Reproduction link
Steps to reproduce
codesandbox使用有问题,换了一个复现的链接,看这里
https://stackblitz.com/edit/react-zcgdmp5t-qzgwbljr?file=demo.tsx,index.tsx
程序首先给数组实例设置了长度为4的默认值,并且给每个字段实例设置了 disabled = true
复现操作:一直删除0号位置的元素
What is expected?
逐一删除0号位置的元素,删除第二个时禁用状态保留,观察form.fields,array.0.input的字段实例不应该被重新生成。
What is actually happening?
逐一删除0号位置的元素,删除第二个时会发现禁用状态丢失了,原本应该禁用的组件变成了非禁用的状态,观察form.fields,会发现array.0.input的字段实例被重新生成了。
Package
@formily/[email protected]
debug了一下@formily/core的源码,发现了一个会造成该现象的原因:
数组字段每次执行remove时会调用 spliceArrayState (packages/core/src/shared/internals.ts)
batch(() => {
each(fields, (field, identifier) => {
if (isArrayChildren(identifier)) {
if (isAfterNode(identifier)) {
const newIdentifier = moveIndex(identifier)
fieldPatches.push({
type: 'update',
address: newIdentifier,
oldAddress: identifier,
payload: field,
})
}
if (isInsertNode(identifier) || isDeleteNode(identifier)) {
fieldPatches.push({ type: 'remove', address: identifier })
}
}
})
patchFieldStates(fields, fieldPatches)
})
这个函数的作用就是在有元素删除时,重新更新每个数组子元素的在form.fields中的path和对应的实例
问题就出在 each(fields, (field, xxx 对对象类型的key的遍历顺序上,
当第一次执行remove时,遍历的顺序是 array.0.input => array.1.input => array.2.input => array.3.input => array.4.input 没有问题
当第二次执行remove时,遍历的顺序是 array.1.input => array.2.input => array.3.input => array.0.input 此时就会出现问题
array.1.input最先被处理,也就是先重新生成了 array.0.input 和其对应的实例,但是在最后一步遍历 array.0.input 时,命中了fieldPatches.push({ type: 'remove', address: identifier })的逻辑,
刚生成的0号位置的新的实例被错误的删除了!!
我尝试修改 fieldPatches.push({ type: 'remove', address: identifier }) 为 fieldPatches.unshift({ type: 'remove', address: identifier }) 可以解决这个问题
逻辑就是让删除操作先执行,变更的操作后执行来消除这个影响。
The text was updated successfully, but these errors were encountered: