react-admin icon indicating copy to clipboard operation
react-admin copied to clipboard

ReferenceArrayInput with AutocompleteArrayInput clearing input

Open KonkretneKosteczki opened this issue 2 years ago • 1 comments

I wanted to create AutocompleteArrayInput within ReferenceArrayInput,

What you were expecting:

I expected to be able to choose from the list elements just fine.

What happened instead:

Whenever I start typing in the autocompleteArrayInput, when there is more than one item already selected, the choice list gets updated, then the value I have written into the input gets cleared, and the suggestion list gets updated again. It makes it almost impossible to use the form. flickering

Steps to reproduce:

I am using react-admin-firebase (not sure if that's important). I created a form with an input:

<ReferenceArrayInput
    source="qualifyingTasks"
    reference="Tasks"
>
    <AutocompleteArrayInput
        filterToQuery={(q) => ({name: q})}
        optionText={(record) => record.name}
    />
</ReferenceArrayInput>

It seems to be enough to reproduce the issue. Just keep adding tasks to the form and eventualy it will end up clearing the typed text.

Can't seem to be able to reproduce the issue using the ra-data-fakerest, It might be related to react-admin-firebase library somehow.

Environment

  • React-admin version: 4.3.3
  • Last version that did not exhibit the issue (if applicable): -
  • React version: 17.0.2
  • Browser: Chrome
  • Stack trace (in case of a JS error): -

KonkretneKosteczki avatar Sep 20 '22 15:09 KonkretneKosteczki

I seem to have managed to mitigate the issue by setting clearOnBlur option to false. Now the question is why does this happen exactly?

KonkretneKosteczki avatar Sep 22 '22 12:09 KonkretneKosteczki

I had the similar issue on react-admin 4.3.1. An update to last 4.3.4 version improved it to a usable level in my case without clearOnBlur={false}. It is still happen but less often.

PawelSuwinski avatar Sep 27 '22 10:09 PawelSuwinski

After all I also ended up with clearOnBlur={false} to have robust solution. Also for that moment couldn't reproduce it using default CodeSanbox. I am using react-admin with api-platform.

PawelSuwinski avatar Sep 28 '22 11:09 PawelSuwinski

If you can't reproduce it with the codesandbox, it's possible that it's caused by a third-party data provider. Another possibility is that the CodeSandbox shows a small delay for dataProvider responses, and this is a race condition that only shows for larger delays.

In any case, we need a reproduction to start investigating this issue.

fzaninotto avatar Oct 20 '22 09:10 fzaninotto

@fzaninotto it seems that I have managed to reproduce this bug. Please check the following CodeSandbox or the repo.

Steps to reproduce the bug:

  1. Open users -> user #112 (url path /#/user/112)
  2. Start typing

magicxor avatar Nov 21 '22 17:11 magicxor

Another reproduction was passed in #8410

fzaninotto avatar Nov 23 '22 09:11 fzaninotto

I don't reproduce this issue in v4.6.1 in our storybook with the following (edited) story inside https://github.com/marmelab/react-admin/blob/master/packages/ra-ui-materialui/src/input/AutocompleteArrayInput.stories.tsx :

const BookEditWithReference = () => (
    <Edit
        mutationMode="pessimistic"
        mutationOptions={{
            onSuccess: data => {
                console.log(data);
            },
        }}
    >
        <SimpleForm>
            <ReferenceArrayInput reference="authors" source="author">
                <AutocompleteArrayInput
                    fullWidth
                    //optionText="name"
                    filterToQuery={q => ({ name: q })}
                    optionText={record => record.name}
                />
            </ReferenceArrayInput>
        </SimpleForm>
    </Edit>
);

export const InsideReferenceArrayInput = () => (
    <Admin dataProvider={dataProviderWithAuthors} history={history}>
        <Resource name="authors" />
        <Resource name="books" edit={BookEditWithReference} />
    </Admin>
);

Hence, I'll consider this issue fixed.

slax57 avatar Dec 15 '22 17:12 slax57

Hi @slax57 Thank you for your reply, but I'm afraid that the issue is still here.

I have updated and simplified the repro of #8181 (github, codesandbox) and the repro of #8410 (github, codesandbox)

magicxor avatar Dec 16 '22 06:12 magicxor

@magicxor thanks for your reply and for the sandboxes.

Do you think you could provide a sandbox based on the simple example? I'm having a hard time working with sandboxes pointing to another project because it asks me for permissions to open them and I can't change the code easily.

Thanks

slax57 avatar Dec 16 '22 09:12 slax57

Besides, I had a quick look at the code from your reproduction project, and saw there are many places where you try advanced and custom features, that are beyond the use-cases we support officially.

For instance:

  • Having an <Edit> inside a <Show>
  • Overriding the record in the <SimpleForm> only
  • Having the achievements stored actually on another resource than user
  • Providing a custom format with no parse
  • And so on...

It is still too complex and there are too many places prone to error for us to work with.

When taking your repo and just changing UserEdit with the following content it works flawlessly:

export const UserEdit = () => {
  return (
    <Edit>
      <SimpleForm>
        <ReferenceArrayInput
          label="Achievements"
          source="achievements"
          reference="achievement"
          allowEmpty
          fullWidth
        >
          <AutocompleteArrayInput
            optionText={(o) => o.name}
            //format={formatFunc}
            filterToQuery={createSearchFilter}
            disableClearable
            clearOnBlur={false}
            fullWidth
          />
        </ReferenceArrayInput>
      </SimpleForm>
    </Edit>
  );
};

Hence, I'll still consider this issue fixed, unless you can provide a simpler repro, based on the simple example, and with supported (i.e. documented) use-cases only.

slax57 avatar Dec 16 '22 09:12 slax57

@slax57

Do you think you could provide a sandbox based on the simple example?

Sure. Please take a look: https://codesandbox.io/s/stupefied-cray-7n3gbo?file=/src/index.tsx

Basically, my API returns a post:

        {
            id: 10,
            title: 'Totam vel quasi a odio et nihil',
            teaser:
                'Excepturi veritatis velit rerum nemo voluptatem illum tempora eos. Et impedit sed qui et iusto. A alias asperiores quia quo.',
            body:
                '<p>Voluptas iure consequatur repudiandae quibusdam iure. Quibusdam consequatur sit cupiditate aut eum iure. Provident ut aut est itaque ut eligendi sunt.</p><p>Odio ipsa dolore rem occaecati voluptatum neque. Quia est minima totam est dicta aliquid sed. Doloribus ea eligendi qui odit. Consectetur aut illum aspernatur exercitationem ut. Distinctio sapiente doloribus beatae natus mollitia. Nostrum cum magni autem expedita natus est nulla totam.</p><p>Et possimus quia aliquam est molestiae eum. Dicta nostrum ea rerum omnis. Ut hic amet sequi commodi voluptatem ut. Nulla magni totam placeat asperiores error.</p>',
            views: 721,
            average_note: 4.121,
            commentable: true,
            published_at: new Date('2012-10-19'),
            tags: [
                // my API returns objects, not just IDs:
                {
                    id: 2,
                    name: 'Technology',
                    published: false,
                },
                {
                    id: 4,
                    name: 'Photo',
                    published: false,
                }
            ],
            category: 'lifestyle'
        }

I want to edit the tags property of this post:

export const formatFunc = (tags: any[]) => tags.map((tag: { id: number }) => tag.id);

export const parseFunc = (tagIds: number[]) => tagIds.map((id: number) => ({ id }));
<ReferenceArrayInput
    reference="tags"
    source="tags"
    label="Tags"
>
    <AutocompleteArrayInput
        optionText={'name'}
        format={formatFunc}
        parse={parseFunc}
        filterToQuery={q => ({ name: q })}
    />
</ReferenceArrayInput>

But search doesn't work properly in this input: firefox_rxDeIGk9b3

magicxor avatar Dec 16 '22 14:12 magicxor

@magicxor Thanks for the repro.

            tags: [
                // my API returns objects, not just IDs:
                {
                    id: 2,
                    name: 'Technology',
                    published: false,
                },
                {
                    id: 4,
                    name: 'Photo',
                    published: false,
                }
            ],

// my API returns objects, not just IDs:

That's actually the cause of the error. <ReferenceArrayInput> only supports an array of ids as source.

With format and parse you can only change the format of the value in the input element, but the value in the record needs to be of the expected shape.

If your API returns objects you probably need to tweak your dataProvider to transform them into an array of ids to be usable by <ReferenceArrayInput>.

slax57 avatar Dec 16 '22 16:12 slax57

Btw @magicxor , you might be interested in this PR if you are looking for a way to add lifecycle callbacks to your dataProvider :wink:

slax57 avatar Dec 19 '22 09:12 slax57