Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reactjs - Update options by hitting API on every input change in Autocomplete component (Material UI)

I am a beginner in Reactjs. I want to create an Autocomplete component where on every input change the API is hit and the options are updated accordingly. I am using the Autocomplete component provided by Material UI. As I understand, the example given here hits an API once and filters it locally. I tried using the InputChange props provided by material component. Also I found this anser - https://stackoverflow.com/a/59751227/8090336. But can't figure out the right way.

import Autocomplete from "@material-ui/lab/Autocomplete";
import TextField from "@material-ui/core/TextField";
import {CircularProgress} from "@material-ui/core";
import debounce from 'lodash/debounce';

const SelectField = ({inputLabel}) => {
    const [ open, setOpen ] = React.useState(false);
    const [ options, setOptions ] = React.useState([]);
    const [ inputValue, setInputValue ] = React.useState("");
    const loading = open && options.length === 0;

    const onInputChange = debounce((event, value) => {
        console.log("OnInputChange",value);
        setInputValue(value);
        (async() => {
            const response = await fetch('https://api.tvmaze.com/search/shows?q='+inputValue);
            console.log("API hit again")
            let movies = await response.json();

            if(movies !== undefined) {
                setOptions(movies);
                console.log(movies)
            }
        })();
    }, 1500);

    return (
        <Autocomplete
            style={{ width:300 }}
            open={open}
            onOpen={() => {
              setOpen(true);
            }}
            onClose={() => {
              setOpen(false);
            }}
            getOptionLabel={(option) => option.show.name}
            onInputChange={onInputChange}
            options={options}
            loading={loading}
            renderInput={(params) => (<TextField
                {...params}
                label={inputLabel}
                variant="outlined"
                InputProps={{
                  ...params.InputProps,
                  endAdornment: (
                      <React.Fragment>
                          {loading ? <CircularProgress color="inherit" size={20} />: null }
                          {params.InputProps.endAdornment}
                      </React.Fragment>
                  ),
                }}
              />
            )}
        />
    );
}

export default SelectField;
like image 952
gowthz Avatar asked May 23 '20 09:05

gowthz


People also ask

How do I use autocomplete in material UI?

There are two versions of the autocomplete that can be used: Combo box — Where the value of the text input must be chosen from a predefined set of values. Free solo — Where the text input can contain any value but is suggested from a list of possible values.

How do I change the style of material UI autocomplete list?

One way of doing this is by adjusting the elevation of the Paper component used by Autocomplete . The default elevation is 1. The example below uses a value of 8 by specifying that in a custom Paper component ( CustomPaper ) which is then provided via the PaperComponent prop of Autocomplete .

How do I add a value to autocomplete material UI?

MUI Autocomplete Get Selected Value I used the onChange handler to pass the selected option to the state value's setter. If we want to get the Autocomplete's selected value for use with a form submission, we only need to wrap the Autocomplete in a form element and add a Button with type="submit" .

How do I use autofill in react JS?

The React AutoComplete supports the autofill behavior with the help of autofill property. Whenever you change the input value and press the down key, the AutoComplete will autocomplete your data by matching the typed character. Suppose, if no matches found then, AutoComplete doesn't suggest any item.

Is it possible to use autocomplete with material UI?

I am using the Autocomplete component provided by Material UI. As I understand, the example given here hits an API once and filters it locally. I tried using the InputChange props provided by material component.

How to fetch/call an API with react?

How to Fetch/Call an API with React 1 Create a Basic Project Structure Make a new folder. I named mine react-api-call. ... 2 Add React Component Back in the terminal run these two commands: npm init -y: Creates an npm package in our project root npm install babel-cli@6 babel-preset-react-app@3: Installs the packages ... 3 Add API Calls

What is a side effect in react?

When building a component using React there is often a requirement to create a side effect when one of the component props changes. This could be a call to an API to fetch some data, manipulating the DOM, updating some component state, or any number of things.

Do I need an API-key for my react app?

Therefore, whether you build a React app this way, or whether you use Create-React-App, if the React code is in the front-end it should not have an API-key. This might leave you wondering, so what do I do?


1 Answers

I had faced this problem I manually called the API when ever the user types in. find the link for the sandbox. Check the onChange prop for the textfield rendered inside the autocomplete

// *https://www.registers.service.gov.uk/registers/country/use-the-api*
import fetch from "cross-fetch";
import React from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";
import CircularProgress from "@material-ui/core/CircularProgress";


export default function Asynchronous() {
  const [open, setOpen] = React.useState(false);
  const [options, setOptions] = React.useState([]);
  const loading = open && options.length === 0;


  const onChangeHandle = async value => {
// this default api does not support searching but if you use google maps or some other use the value and post to get back you reslut and then set it using setOptions 
    console.log(value);

    const response = await fetch(
      "https://country.register.gov.uk/records.json?page-size=5000"
    );

    const countries = await response.json();
    setOptions(Object.keys(countries).map(key => countries[key].item[0]));
  };

  React.useEffect(() => {
    if (!open) {
      setOptions([]);
    }
  }, [open]);

  return (
    <Autocomplete
      id="asynchronous-demo"
      style={{ width: 300 }}
      open={open}
      onOpen={() => {
        setOpen(true);
      }}
      onClose={() => {
        setOpen(false);
      }}
      getOptionSelected={(option, value) => option.name === value.name}
      getOptionLabel={option => option.name}
      options={options}
      loading={loading}
      renderInput={params => (
        <TextField
          {...params}
          label="Asynchronous"
          variant="outlined"
          onChange={ev => {
            // dont fire API if the user delete or not entered anything
            if (ev.target.value !== "" || ev.target.value !== null) {
              onChangeHandle(ev.target.value);
            }
          }}
          InputProps={{
            ...params.InputProps,
            endAdornment: (
              <React.Fragment>
                {loading ? (
                  <CircularProgress color="inherit" size={20} />
                ) : null}
                {params.InputProps.endAdornment}
              </React.Fragment>
            )
          }}
        />
      )}
    />
  );
}


like image 192
joy son Avatar answered Oct 17 '22 06:10

joy son