Reputation: 61
I'm trying to update the values of a ReferenceArrayInput (react-admin v5) when I click in a button but its not working as expected.
I'm using the setValue
of the UseFormContext()
from react-hook-form
package to change the value of a specific input like this:
import { useFormContext } from 'react-hook-form';
const { setValue, getValues } = useFormContext();
console.log('inputValue', getValues('content'));
const newIds: any = [
'66602e19d8d796f4516625d9',
'669e1d0d309249d0b70446a1',
'669e1c0e309249d0b7044665',
'666061d6a6ad59738546c169',
'669e1da6309249d0b70446ce',
'669e1c39309249d0b704466f',
'669e1dec309249d0b70446ee',
'666061a0a6ad59738546c139',
'6660620ba6ad59738546c19f',
'6660347bd8d796f451662853',
'669e1d7b309249d0b70446b5',
];
const handleClick = () => {
setValue('content', newIds, { shouldDirty: true });
};
return (
<>
<ReferenceArrayInput
resource={resource}
reference={reference}
source={'content'}
allowEmpty
>
<AutocompleteArrayInput optionText="title" />
</ReferenceArrayInput>
<Button onClick={handleClick} label="test" />
</>
);
Result Obtained:
The input value is being updated and the form recognizes it as a change, but the input UI always remains the same. however if I save the changes and return to this view again, it already appears with the new order.
Before updating the order:
After updating the order:
As you can see in the log, the input value was updated but in the UI it stayed the same. I want to update the input UI as soon as its value is updated.
Any idea of what could be the cause of this?
Upvotes: 0
Views: 77
Reputation: 3319
You can manually trigger an interface update:
const refresh = useRefresh();
...
const handleClick = () => {
setValue('content', newIds, { shouldDirty: true });
refresh();
};
Upvotes: 0
Reputation: 591
I think I found it.
It turns out React Admin performs some checks to detect whether or not the selected choices have changed, and whether it should rerender:
if (selectedChoiceArray.length !== newSelectedChoiceArray.length) {
return false;
}
const equalityArray = selectedChoiceArray.map(choice =>
newSelectedChoiceArray.some(
newChoice =>
get(newChoice, optionValue) === get(choice, optionValue)
)
);
return !equalityArray.some(item => item === false);
As you can see, this code checks if the number of selected items has changed, or if one of the items in the list does not have the same value.
In your case, since all you do is change the order, this code returns that nothing has changed, and hence does not trigger a re-render.
I'm not sure this is something that should be changed at the react-admin level, as I'm afraid removing this optimization could have undesired side-effects.
Nevertheless, you can open an issue on their repo if you'd like to suggest this change.
In the meantime, here is a (somewhat awful) hack that I found which can serve as a workaround: you can call setValue
twice, once with an extra value, and then with the desired (ordered) value.
This will trigger the rerender so the UI will be updated.
Example:
const handleClick = () => {
setValue('content', [...newIds, '']);
setTimeout(() => {
setValue('content', newIds, { shouldDirty: true });
});
};
Upvotes: 1