Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent get request from being send if the length of the query field is short in react-admin

Tags:

react-admin

I'm using react-admin and trying to create a filter with autocomplete field that will make a query as I type and will only start sending the query when the search criteria length is longer then 2.

I'm currently using shouldRenderSuggestions inside of my AutocompleteInput field but this still send two requests with an empty string in the "nickname" filter, this is the code part:

<AutocompleteInput optionText="nickname" shouldRenderSuggestions={(val) => {
        return val.trim().length > 2
      }}/>

The thing that happens is when I fill in the first and second letters the GET request is sent but with an empty string in the nickname field,

The string input is for example:"abc":

1ST request: http://website.loc/clients?filter={"nickname":""}&page=1&perPage=25&range=[0,24]&sort=["id","DESC"]

2ND request: http://website.loc/clients?filter={"nickname":""}&page=1&perPage=25&range=[0,24]&sort=["id","DESC"]

3RD request: http://website.loc/clients?filter={"nickname":"abc"}&page=1&perPage=25&range=[0,24]&sort=["id","DESC"]

I want to avoid from sending the first two requests entirely.

The full code of the component:

const PostPagination = props => (
  <Pagination rowsPerPageOptions={[]} {...props} />
);

const PostFilter = (props) => (
  <Filter {...props}>
    <ReferenceInput label="Client"
                    source="client_id"
                    reference="clients"
                    allowEmpty
                    filterToQuery={searchText => ({ nickname: searchText })}>
      <AutocompleteInput optionText="nickname" shouldRenderSuggestions={(val) => {
        return val.trim().length > 2
      }}/>
    </ReferenceInput>
  </Filter>
);

const PostsList = props => {
  return (
    <List {...props} perPage={15}
          pagination={<PostPagination/>}
          filters={<PostFilter/>}
          exporter={false}>
      <Datagrid>
        <TextField source="nickname" sortable={false}/>
        <DateField label="Created" source="created_at" showTime/>
      </Datagrid>
    </List>
  );
};

Edit: same question goes for "search-as-you-type" fields like <TextInput> inside a <Filter> field, I started to ask a new question but realized it will be kind of a duplicate,

This is the code that also sends requests starting from 1 char, in this case there isn't even a shouldRenderSuggestions option to force it to send empty requests

const ClientFilter = (props) => (
  <Filter {...props}>
    <TextInput label="Search" source="str" alwaysOn/>
  </Filter>
);

Live example of code in codesandbox.io

like image 836
Adi Bnaya Avatar asked Mar 11 '19 10:03

Adi Bnaya


1 Answers

I stumbled upon this issue, too. The best I've come up with so far is a small wrapper component that prevents the ReferenceInput from triggering API requests unless a certain condition is met:

  const ConditionalFilter = (props) => {
    const { children, condition, setFilter } = props;
    const conditionalSetFilter = (val) => {
      if (setFilter && condition(val)) setFilter(val);
    };
    return React.cloneElement(children, { ...props, setFilter: conditionalSetFilter });
  };

Used like this:

  const condition = val => val.trim().length > 2;
  return (
    <ReferenceInput 
      source="…"
      reference="…"
      shouldRenderSuggestions={condition}
    >
      <ConditionalFilter condition={condition}>
        <AutocompleteInput />
      </ConditionalFilter>
    </ReferenceInput>
  );

Update for react-admin v3: (without the wrapper component, which is no longer necessary/useful)

const condition = (val) => !!val && val.trim().length > 2;
return (
  <ReferenceInput
    source="…"
    reference="…"
    filterToQuery={(val) => (condition(val) ? { name: val.trim() } : {})}
  >
    <AutocompleteInput shouldRenderSuggestions={condition} />
  </ReferenceInput>
);
like image 65
d0gb3r7 Avatar answered Oct 16 '22 07:10

d0gb3r7