代码之家  ›  专栏  ›  技术社区  ›  AlainIb

material-ui使用异步自动补全

  •  0
  • AlainIb  · 技术社区  · 5 年前

    我试着用材料ui useAutocomplete 使用异步调用。 简单的案例 autocomplete 工作,但我需要调整输入集中时显示的对话框,所以我必须使用 使用自动补全 .

    所以我尝试合并这段代码(async): https://codesandbox.io/s/pvjgx

    对于这个(使用自动补全): https://codesandbox.io/s/261pd?file=/demo.js

    问题是我不知道放在哪里或怎么放 onChange 这样我就可以触发获取数据的async函数

    这是我到目前为止得到的不工作的代码(不工作的沙盒) 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>
      );
    }
    

    欢迎提供任何建议

    0 回复  |  直到 5 年前
        1
  •  0
  •   Jannik    5 年前

    你在问题中复制了两次相同的链接,所以我真的不知道你想实现什么。 我正在使用带有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);
        };
    

    一切都在异步运行。

    也许可以试着进一步澄清你的问题,这样我就可以改进我的答案了:)