Skip to content
New issue

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

Add an option to make ReferenceArrayInput lazy #5898

Closed
ValentinH opened this issue Feb 11, 2021 · 4 comments
Closed

Add an option to make ReferenceArrayInput lazy #5898

ValentinH opened this issue Feb 11, 2021 · 4 comments

Comments

@ValentinH
Copy link
Contributor

Is your feature request related to a problem? Please describe.
I'm building an edit form where one of the input is an ArrayInput. Each item of this input is a SimpleFormIterator with a few fields. Some of these fields are using a ReferenceArrayInput with an AutocompleteArrayInput.

Here's an example:

const Demo = (props: EditProps) => {
  return (
    <Edit {...props}>
      <SimpleForm redirect="/suspicious-articles-rules">
        <TextInput source="title" label="Title" validate={[required()]} />
        <TextInput source="description" multiline rows={4} />
        <ArrayInput source="items">
          <SimpleFormIterator>
            <ReferenceArrayInput
              reference="categories"
              source="categories.include"
              label="Include categories"
            >
              <AutocompleteArrayInput
                optionText={(option: Category | undefined) =>
                  option ? `${option.name} (${option.id})` : ''
                }
                shouldRenderSuggestions={(value: string) => value.trim().length >= 2}
              />
            </ReferenceArrayInput>
            <ReferenceArrayInput
              reference="categories"
              source="categories.exclude"
              label="Exclude categories"
            >
              <AutocompleteArrayInput
                optionText={(option: Category | undefined) =>
                  option ? `${option.name} (${option.id})` : ''
                }
                shouldRenderSuggestions={(value: string) => value.trim().length >= 2}
              />
            </ReferenceArrayInput>
            <NumberInput label="Price (from)" source="price_range.from" fullWidth />
          </SimpleFormIterator>
        </ArrayInput>
      </SimpleForm>
    </Edit>
  )
}

The categories resource has a lot of items and so I'd like to fetch them only if the user enters at least 2 characters. However, even if the autocomplete doesn't show the option, each ReferenceArrayInput is fetching the data with no q param (/categories?_end=25&_order=DESC&_sort=id&_start=0).

Another issue I noticed is that requests from the ReferenceArrayInput are not batched. In the above example, if I'm editing a resource with 3 items, there are 6 requests sent to /categories?_end=25&_order=DESC&_sort=id&_start=0 when opening the form.

Describe the solution you'd like
Ideally, a lazy option would be nice. Its purpose would be to only fetch the data for an autocomplete if the shouldRenderSuggestions returns true.

Describe alternatives you've considered
Another possibility would be to have all similar requests batched in the example I mentioned above.

@fzaninotto
Copy link
Member

As I understand it, you have two ReferenceArrayInput on the same reference but with different sources.

The fact that ReferenceArrayInput fetches the possible options on mount is by design. If you want a component that does it lazily, you'll have to write your own.

As for not batching the calls for the possible values, I'm not sure I can reproduce. In the simple example, where we have an ArrayInput, if I edit a post and add several authors to it, then navigate away and back, I can see that the form only loads the list of possible authors once.

So for this second problem, please attach a link to a fork of the simple codesandbox demonstrating the issue.

Finally, please follow the issue template so that we know at least the version of react-admin you're using.

@ValentinH
Copy link
Contributor Author

Yes you understand it right. Given that they are in an ArrayInput, the cardinality is doubled and we can end up with tons of calls though.

I'll look into making my own then.

Regarding the codesandbox, I actually tried to use it yesterday but I see a white page on https://codesandbox.io/s/github/marmelab/react-admin/tree/master/examples/simple. There is an error about Cannot find module "ra-ui-materialui". After adding it, it worked fine.

Thus, here an example showing what I wrote regarding batching: https://codesandbox.io/s/zealous-leakey-o5oxt?file=/src/posts/PostEdit.js (output-only version).
There I modified to PostEdit to have 3 tags input on the first tab. As you can see in the console and in the screenshot below, there are 3 getList calls made to fetch the tags. This is what I would expect to be batched:
image

Finally, I actually followed the issue template but it was the "feature request" one.

@ValentinH
Copy link
Contributor Author

I think that in order to have a "lazy" behaviour while still using the useGetList hook, I will actually need the enabled option I suggested in #5849 😅

@WiXSL
Copy link
Contributor

WiXSL commented Jan 27, 2022

Implemented in #6013 for ReferenceInput and ReferenceArrayInput

@WiXSL WiXSL closed this as completed Jan 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants