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

AutocompleteInput resets input when useChoicesContext is called #9876

Open
wattry opened this issue May 23, 2024 · 3 comments
Open

AutocompleteInput resets input when useChoicesContext is called #9876

wattry opened this issue May 23, 2024 · 3 comments

Comments

@wattry
Copy link

wattry commented May 23, 2024

What you were expecting:
useChoiceContext can be called in the scope of a ReferenceInput wrapped AutocompleteInput .

What happened instead:
When trying to use the useChoicesContext inside a nested AutocompleteInput calling useChoicesContext causes the input to reset when the user enters values.

Related code:

On the stackblitz link navigate to the comments app and select a comment to edit. On the first Post input try search a new value. The input will be cleared every time you finish typing.

On the second posts input the isLoading value has be set to true. However, no loading indicator or text is displayed.

https://stackblitz.com/edit/github-guchrk?file=src%2Fcomments%2FCommentEdit.tsx

function AutocompleteLoading(props) {
  // This call prevents the user from typing. If commented out
  // you will be able to enter input.
  const choiceContext = useChoicesContext(props);

  return (
    <AutocompleteInput
      create={<CreatePost />}
      matchSuggestion={(filterValue, suggestion) => {
        const title = `${suggestion.title} - ${suggestion.id}`;
        return title.includes(filterValue);
      }}
      optionText={<OptionRenderer />}
      inputText={inputText}
      fullWidth
    />
  );
}
<ReferenceInput
      source="post_id"
      reference="posts"
      perPage={15}
      sort={{ field: 'title', order: 'ASC' }}
    >
  <AutocompleteLoading />
</ReferenceInput>

Other information:

Our users have complained that the autocomplete (in this use case) does not indicate that it is loading. When trying to use a isLoading flag we noticed that we could no longer enter input when we got the isLoading from the useChoicesContext. Separately even if you put the isLoading flag set to true the spinning wheel that is on the SelectInput is not shown.

Environment

    "react": "18.2.0",
    "react-admin": "4.16.18",
    "react-dom": "18.2.0",
  • React-admin version: 4.16.18
  • Last version that did not exhibit the issue (if applicable):
  • React version: 18.2.0
  • Browser: Chrome
  • Stack trace (in case of a JS error): N/A
@slax57 slax57 added the bug label May 24, 2024
@slax57
Copy link
Contributor

slax57 commented May 24, 2024

Thanks for submitting this report.

There may be a bug in AutocompleteInput which causes undesired rerenders. This requires more investigation.
I'll label this as a bug for now.

As a workaround, you can simply memoize the component:

function AutocompleteLoading(props) {
  // This call prevents the user from typing. If commented out
  // you will be able to enter input.
  const { isFetching } = useChoicesContext(props);

  const memoizedAutocompleteInput = React.useMemo(
    () => (
      <AutocompleteInput
        create={<CreatePost />}
        matchSuggestion={(filterValue, suggestion) => {
          const title = `${suggestion.title} - ${suggestion.id}`;
          return title.includes(filterValue);
        }}
        optionText={<OptionRenderer />}
        inputText={inputText}
        // fullWidth
        sx={{ minWidth: 380 }}
      />
    ),
    []
  );

  return (
    <Stack direction="row">
      {memoizedAutocompleteInput}
      {isFetching ? <CircularProgress /> : null}
    </Stack>
  );
}

Note: you should use isFetching instead of isLoading, as I did in this example, because isLoading will only be true while loading the data for the first time.

Demo stackblitz: https://stackblitz.com/edit/github-guchrk-pdjjdp?file=src%2Fcomments%2FCommentEdit.tsx

@wattry
Copy link
Author

wattry commented May 28, 2024

Thanks for submitting this report.

There may be a bug in AutocompleteInput which causes undesired rerenders. This requires more investigation. I'll label this as a bug for now.

As a workaround, you can simply memoize the component:

function AutocompleteLoading(props) {
  // This call prevents the user from typing. If commented out
  // you will be able to enter input.
  const { isFetching } = useChoicesContext(props);

  const memoizedAutocompleteInput = React.useMemo(
    () => (
      <AutocompleteInput
        create={<CreatePost />}
        matchSuggestion={(filterValue, suggestion) => {
          const title = `${suggestion.title} - ${suggestion.id}`;
          return title.includes(filterValue);
        }}
        optionText={<OptionRenderer />}
        inputText={inputText}
        // fullWidth
        sx={{ minWidth: 380 }}
      />
    ),
    []
  );

  return (
    <Stack direction="row">
      {memoizedAutocompleteInput}
      {isFetching ? <CircularProgress /> : null}
    </Stack>
  );
}

Note: you should use isFetching instead of isLoading, as I did in this example, because isLoading will only be true while loading the data for the first time.

Demo stackblitz: https://stackblitz.com/edit/github-guchrk-pdjjdp?file=src%2Fcomments%2FCommentEdit.tsx

Thanks that worked

@fzaninotto fzaninotto removed the bug label Oct 3, 2024
@djhi
Copy link
Collaborator

djhi commented Nov 14, 2024

It's actually not related to the call to useChoicesContext. It's because you currently have to memoize the values you provide to props accepting a function or an element. See https://stackblitz.com/edit/github-guchrk-vwc9uq?file=src%2Fcomments%2FCommentEdit.tsx

This means the workaround should be to make those props values referentially stable, either by extracting them outside the component as in the stackblitz above or by applying classic react memoization.

However, we should make it easier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants