material-ui use通过异步自动完成

时间:2020-06-15 18:40:03

标签: material-ui useautocomplete

我正在尝试将material-ui useAutocomplete与异步调用一起使用。 使用autocomplete很简单,但是我需要调整输入焦点时显示的对话框,因此我必须使用useAutocomplete

所以我尝试合并此代码(异步):https://codesandbox.io/s/pvjgx

与此(useAutocomplete):https://codesandbox.io/s/261pd?file=/demo.js

问题是我不知道在哪里或如何将onChange放入输入中,因此我可以触发获取数据的异步函数

这是我到目前为止得到的无效代码(无效的沙箱)https://codesandbox.io/s/material-demo-gl9pw?file=/demo.js

import React from "react";
import useAutocomplete from "@material-ui/lab/useAutocomplete";

import { InputBase } from "@material-ui/core";
import CircularProgress from "@material-ui/core/CircularProgress";

import styled from "styled-components";

import { makeStyles } from "@material-ui/core/styles";

const Listbox = styled("ul")`
  width: 300px; margin: 2px 0 0;padding: 0;position: absolute; list-style: none; background-color: #fff;overflow: auto;max-height: 250px; border-radius: 4px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); z-index: 1;
  & li {padding: 5px 12px; display: flex; & span {flex-grow: 1; }& svg { color: transparent; } }
  & li[aria-selected="true"] { background-color: #fafafa; font-weight: 600; & svg {color: #1890ff;}}
  & li[data-focus="true"] {background-color: #e6f7ff; cursor: pointer; & svg { color: #000; } }
`;

const useStyles = makeStyles(theme => ({
  autoWidth: {width: "auto"},
  input: {
    marginLeft: theme.spacing(1),
    flex: 1,
    color: "white",
    textAlign: "center",
    align: "center",
    "& input": {
      textAlign: "center"
    }
  },
  iconButton: {
    padding: 10,
    color: "white"
  },
  searchRoot: {
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    backgroundColor: "blue"
  }
}));

export default function MyAutocomplete() {
  const classes = useStyles();

  const [value, setValue] = React.useState("");
  const [open, setOpen] = React.useState(false);
  const [options, setOptions] = React.useState([]);
  const loading = open && options.length === 0;

  React.useEffect(() => {
    let active = true;

    if (!loading) { return undefined; }

    console.log("run")(async () => {
      const response = await fetch("https://country.register.gov.uk/records.json?page-size=5000");
      const countries = await response.json();

      if (active) {
        setOptions(Object.keys(countries).map(key => countries[key].item[0]));
      }
    })();

    return () => {
      active = false;
    };
  }, [loading]);

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

  const {
    getRootProps, getInputLabelProps, getInputProps, getListboxProps, getOptionProps, groupedOptions, focused, setAnchorEl
    // value
  } = useAutocomplete({
    id: "customized-autocomplete-async",
    options: options,
    getOptionLabel: option => option.name
  });

  return (
    <div className={classes.autoWidth}>
      <div {...getRootProps()}>
        <InputBase
          {...getInputProps()}
          //value={value}
          //onChange={event => {setValue(event.target.value);          }}
          inputRef={setAnchorEl}
          className={classes.input}
          placeholder="Localisation"
          inputProps={{ "aria-label": "Localisation" }}
          fullWidth={true}
          endAdornment={
            <React.Fragment>
              {loading ? <CircularProgress color="inherit" size={20} /> : null}
            </React.Fragment>
          }
        />
      </div>
      {focused && (
        <div className={classes.autoWidth}>
          <Listbox {...getListboxProps()}>
            <div> Localiser moi ! </div>
            <br />
            {groupedOptions.map((option, index) => (
              <li {...getOptionProps({ option, index })}>
                <span>{option.title}</span>
              </li>
            ))}
          </Listbox>
        </div>
      )}
    </div>
  );
}

欢迎任何提示

1 个答案:

答案 0 :(得分:0)

您在问题中复制了两次相同的链接,所以我真的不知道您想要实现什么。 我正在将自动完成功能与TextField输入配合使用:

                <Autocomplete
                    options={ isValidating ? [{nickname: '...loading'}] : data ? data : [] }
                    getOptionLabel={(option) => option.nickname}
                    id="auto-complete"
                    autoComplete
                    includeInputInList
                    value={value}
                    onChange={(event, newValue) => {
                    setValue(newValue);
                    }}
                    onInputChange={(event, newInputValue) => {
                       console.log(newInputValue);
                      }}
                    renderInput={(params) => <TextField {...params} error={error} helperText={error} label="Email Address or User ID" value={query} onChange={handleChange} margin="normal" />}
            />

并使用Swr提取数据:

    const [query, setQuery] = React.useState('');
    const [value, setValue] = React.useState()
    const [loading, setLoading] = React.useState(false)

    const { data, isValidating } = useSwr(active && query.length > 2 ? '/api/getusers?q='+query : '', fetcher)

    const handleChange = (event) => {
      setQuery(event.target.value);
    };

一切都异步运行。

也许可以尝试进一步澄清您的问题,以便我改善回答:)