Closed Ragnaxander closed 4 years ago
i got it
@yoyo837 , What's means about this link? how did it work for this issue?
Hey @dukeliberal
Looks like ant-design documentation now includes a chapter on this: https://ant.design/components/form/#setFieldsValue-do-not-trigger-onFieldsChange-or-onValuesChange :
Here's what it says:
> setFieldsValue do not trigger onFieldsChange or onValuesChange?
It's by design. Only user interactive can trigger the change event. This design is aim to avoid call setFieldsValue in change event which may makes loop calling.
Hey @dukeliberal
Looks like ant-design documentation now includes a chapter on this: https://ant.design/components/form/#setFieldsValue-do-not-trigger-onFieldsChange-or-onValuesChange :
Here's what it says:
> setFieldsValue do not trigger onFieldsChange or onValuesChange? It's by design. Only user interactive can trigger the change event. This design is aim to avoid call setFieldsValue in change event which may makes loop calling.
Thank u, guy.
Hey @dukeliberal
Looks like ant-design documentation now includes a chapter on this: https://ant.design/components/form/#setFieldsValue-do-not-trigger-onFieldsChange-or-onValuesChange :
Here's what it says:
> setFieldsValue do not trigger onFieldsChange or onValuesChange? It's by design. Only user interactive can trigger the change event. This design is aim to avoid call setFieldsValue in change event which may makes loop calling.
This decision doesn't make sense to me. I usually have to make dumb setStates to update the UI because setFields do nothing.
i think that this method have to has options
property, like setFieldsValue(values, { triggerFieldsChange: boolean, triggerValuesChange: boolean })
. that will trigger onFieldsChange or onValuesChange if their values are true.
I'm done with AntD Form, this is by far the worst form you can work with. I'm switching to react-hook-form
. The API sucks, validating a form is a pain and all this is a waste for time :(
You can also use the following hack as a replacement for onFieldsChange
:
<Form.Item shouldUpdate>
{((isParentRender) => () => {
// using this instead of Form.onValuesChange prop
// because the last one will not be triggered on form.setFieldValue()
if (isParentRender) {
// do not execute any logic on parent component render to avoid render loops
isParentRender = false;
return;
}
// use timeout because this callback is executed in rendering
// context where setState is not expected
setTimeout(() => {
const values = form.getFieldsValue();
const result = doSomeStaff(values);
setSomeState(result);
});
return null;
})(true)}
</Form.Item>
Not that pretty, but should work as expected :sweat_smile:
I believe it would be beneficial to create a new API separate from 'onFieldsChange' and 'onValuesChange'. This new API could accommodate recursive calls, leaving the responsibility of handling these calls to the user. This would provide more flexibility without altering the behavior of existing APIs. Please consider this suggestion for future updates. Thank you.
One way is to 'fool' onValuesChange() by simulating real interaction, calling the native API directly; ie. call native setter and 'change' event dispatch like so:
export function setInputField ({id, value}) {
// set input value
var input = document.getElementById(id);
var nativeInputValueSetter = Object.getOwnPropertyDescriptor(
window.HTMLInputElement.prototype, "value").set;
nativeInputValueSetter.call(input, value);
// dispatch change event
var inputEvent = new Event("change", { bubbles: true });
input.dispatchEvent(inputEvent);
}
Another solution might be using the internal hooks api. It's not clean, but unfortunately not all interfaces are given to the outside world.
export function updateFieldValue<Values = any>(form: FormInstance<Values>, name: string, value: any) {
(form as any).getInternalHooks('RC_FORM_INTERNAL_HOOKS').dispatch({
type: 'updateValue',
namePath: [name],
value: value
})
}
This will trigger onValuesChange and onFieldsChange, but latter with touched: false
I also use the internal hooks api for change the initial values during the runtime (needed for ui updates/multiuser changes)
export function setFormInitialValues<Values = any>(form: FormInstance<Values>, initialValues: Values | null) {
(form as any).getInternalHooks('RC_FORM_INTERNAL_HOOKS').setInitialValues(initialValues, true)
}
Reproduction link
Steps to reproduce
use form.setFieldsValue for setting new form values.
What is expected?
form.setFieldsValue also fires onFieldsChange or onValuesChange.
What is actually happening?
form.setFieldsValue not fires onFieldsChange or onValuesChange.