9
votes

In the hooks version of material UI I can't seem to be able to clear the autocomplete after an onChange event:

// @flow
import React, { useRef, useState } from "react";
import "./Autocomplete.scss";
import AutocompleteUI from "@material-ui/lab/Autocomplete";
import TextField from "@material-ui/core/TextField";

function Autocomplete(props) {
    const { options } = props;
    const [value, setValue] = useState();

    const container = useRef();
    const input = useRef();

    function onChange(event, newValue) {
        if (!newValue) return;
        props.onChange(newValue);
        setValue(undefined);
        input.current.value = "";
        event.target.value = "";
    }

    function renderInput(params) {
        return (
            <TextField
                inputRef={input}
                {...params}
                inputProps={{
                    ...params.inputProps,
                    autoComplete: "disabled", // disable autocomplete and autofill
                }}
                margin="none"
                fullWidth
            />
        );
    }

    return (
        <div className="Autocomplete-container">
            {value}
            <AutocompleteUI
                ref={container}
                options={options}
                autoHightlight={true}
                clearOnEscape={true}
                autoSelect={true}
                // freeSolo={true}
                getOptionLabel={option => option.title}
                renderInput={renderInput}
                value={value}
                onChange={onChange}
            />
        </div>
    );
}

export default Autocomplete;

Diving into the source code I've noticed the component uses useAutocomplete hook internally. However, neither setInputValue nor resetInputValue which live internally inside that hook are exposed outside. Is there a way to accomplish an input clear after an onChange?

5
By clear the autocomplete, do you mean simply empty the input box, or remove the suggestions?Chris B.
@ChrisB. Yes, the former, I am trying to clear the input box.Guy
Apparently it only works with refs, which is an idiotic design for a reusable React component in my opinion. You'd have to set the value directly on the DOM element, but I'm not familiar with their API.Chris B.
@ChrisB. I have tried working with refs and changing the input's value directly, however as the component itself holds the state (via the useAutocomplete hook) it does not workGuy

5 Answers

4
votes

I had the same issue and I solved it with this :

    const [search, setSearch] = useState("");

...

     <Autocomplete
          id="grouped-demo"
          options={tagsList}
          getOptionLabel={(option) => option.tag}
          onChange={(event, value) =>value ? setSearch(value.tag) : setSearch(event.target.value)}
          style={{width: 700}}
          renderInput={(params) => <TextField {...params} label="Search" variant="outlined"/>}
     />
3
votes

You need to set the inputValue prop to your valueState and on onhange function just clear the valueState

<Autocomplete

inputValue={valueState}

onChange={(value, option) =>
{


    setOptions([])
    setValueState("")

}}

renderInput={params => (
    <TextField
        dir="rtl"
        onChange={(event) =>
        {

            setValueState(event.target.value)

        }}
        {...params}
        label="Search Patient"
        variant="filled"

        InputProps={{
            ...params.InputProps,
            endAdornment: (
                <React.Fragment>
                    {loading ? (
                        <CircularProgress color="inherit" size={20} />
                    ) : null}
                    {params.InputProps.endAdornment}
                </React.Fragment>
            )
        }}
    />
)}
/>
1
votes

I encountered a similar scenario using Autocomplete/Textfield in a Search/Nav bar. The value would always be left behind after using a history.push or other Router function in the onChange event. The trick is to set the inputValue = "" . Every time the component renders, the previous value will be removed. See below

<Autocomplete
  {...defaultProps}
  onChange={(event, value) => {
    if(value) 
      router.history.push(`/summary`);
  }}
  filterOptions={filterOptions}
  clearOnEscape={true}
  inputValue=""
  renderInput={params => <TextField {...params} 
                                    label="Quick Search"  fullWidth                            
                                    InputProps={{...params.InputProps, 
                                      'aria-label': 'description',
                                                disableUnderline: true, 
                           }}/>}
/>
-1
votes

yo! I'm pretty sure the Textfield component from material takes an "autoComplete" prop, and you can pass that the string "false". Also, it does not go in inputProps, try that out.

<Textfield autoComplete="false" />
-3
votes

I had the same issue and I solved it with this :

const [value, setValue] = useState(null);

Then you don't need to use refs.