提问者:小点点

Reactjs-通过在自动完成组件(物料UI)中的每个输入更改点击API来更新选项


我是ReactJS的初学者。我想创建一个自动完成组件,在每个输入更改时,API都会被点击,选项也会相应地更新。我正在使用材料UI提供的自动完成组件。按照我的理解,这里给出的示例命中一次API并在本地过滤它。我尝试使用material组件提供的InputChange道具。我还找到了这个anser-https://stackoverflow.com/A/59751227/8090336。却想不出正确的方法。

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;

共1个答案

匿名用户

我曾经遇到过这个问题,当用户输入时,我手动调用API。找到沙盒的链接。检查autocomplete中呈现的textfield的onChange属性

// *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>
            )
          }}
        />
      )}
    />
  );
}