Luís Fernandes
Luís Fernandes

Reputation: 61

Update ReferenceArrayInput values on button click

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:

enter image description here

enter image description here

After updating the order:

enter image description here

enter image description here

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

Answers (2)

MaxAlex
MaxAlex

Reputation: 3319

You can manually trigger an interface update:

const refresh = useRefresh();
...  
const handleClick = () => {
  setValue('content', newIds, { shouldDirty: true });
  refresh();
};  

Upvotes: 0

slax57
slax57

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);

Source

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

Related Questions