Material-UI自动完成onChange不会更新值

时间:2020-01-13 12:06:07

标签: reactjs material-ui

我想在自动完成组件上使用onChange事件来获取当前选定的值。 问题在于它无法按预期运行,因此当我单击以选中/取消选中值复选框时,仍未选中该复选框,但是在控制台中,我可以看到已添加了新值

此部分不起作用,以使其起作用:

  value={myTempVal}
      onChange={(event, newValue) => {
        setMyTempVal(newValue);
        console.log(newValue);
      }}

在线演示: https://codesandbox.io/embed/hardcore-snowflake-7chnc?fontsize=14&hidenavigation=1&theme=dark

代码:

const [myTempVal, setMyTempVal] = React.useState([]);

<Autocomplete
      open
      multiple
      value={myTempVal}
      onChange={(event, newValue) => {
        setMyTempVal(newValue);
        console.log(newValue);
      }}
      disableCloseOnSelect
      disablePortal
      renderTags={() => null}
      noOptionsText="No labels"
      renderOption={(option, { selected }) => {
        return (
          <>
            <Checkbox
              icon={icon}
              checkedIcon={checkedIcon}
              style={{ marginRight: 8 }}
              checked={selected}
            />
            {option.title}
          </>
        );
      }}
      options={option2}
      // groupBy={option => option.groupName}
      getOptionLabel={option => option.title}
      renderInput={params => (
        <div>
          <div>
            <SearchIcon />
          </div>
          <TextField
            variant="outlined"
            fullWidth
            ref={params.InputProps.ref}
            inputProps={params.inputProps}
          />
        </div>
      )}
    />

3 个答案:

答案 0 :(得分:1)

您需要从函数中获取donors receiversoptions变量。这些变量在每次渲染时都会重新创建,这意味着它们的引用在每次渲染时都会更改,并且当自动完成功能进行参考相等性检查来确定是否选择了某个选项时,他永远找不到所选的选项。

const donors = [...new Set(data.map(row => row.donor))].map(row => {
  return {
    groupName: "Donors",
    type: "donor",
    title: row || "null"
  };
});
const receivers = [...new Set(data.map(row => row.receiver))].map(row => {
  return {
    groupName: "Receivers",
    type: "receiver",
    title: row || "null"
  };
});
const option2 = [...donors, ...receivers];

export const App = props => {

  const [myTempVal, setMyTempVal] = React.useState([]);

  return (
    <Autocomplete
      open
      multiple
...

您还可以添加getOptionSelected来覆盖参考检查:

<Autocomplete
      open
      multiple
      disableCloseOnSelect
      disablePortal
      renderTags={() => null}
      noOptionsText="No labels"
      getOptionSelected={(option, value) => option.title === value.title} 
      renderOption={(option, { selected }) => {
        return (
          <>
            <Checkbox
              icon={icon}
              checkedIcon={checkedIcon}
              style={{ marginRight: 8 }}
              checked={selected}
            />
            {option.title}
          </>
        );
      }}
      options={option2}
      // groupBy={option => option.groupName}
      getOptionLabel={option => option.title}
      renderInput={params => (
        <div>
          <div>
            <SearchIcon />
          </div>
          <TextField
            variant="outlined"
            fullWidth
            ref={params.InputProps.ref}
            inputProps={params.inputProps}
          />
        </div>
      )}
    />

答案 1 :(得分:0)

这可以帮助: 替换

checked={selected}

收件人

checked={myTempVal.filter(obj=>obj.title===option.title).length!==0}

完整的解决方案

import React from "react";
import "./styles.css";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";
import CheckBoxOutlineBlankIcon from "@material-ui/icons/CheckBoxOutlineBlank";
import CheckBoxIcon from "@material-ui/icons/CheckBox";
import Checkbox from "@material-ui/core/Checkbox";
import SearchIcon from "@material-ui/icons/Search";

const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;

const data = [
  { donor: "Trader Joe's", receiver: "Person-to-Person" },
  { donor: "Trader Joe's", receiver: "Homes with Hope" },
  { donor: "Santa Maria", receiver: "Gillespie Center" },
  { donor: "Santa Maria", receiver: null }
];

export const App = props => {
  const donors = [...new Set(data.map(row => row.donor))].map(row => {
    return {
      groupName: "Donors",
      type: "donor",
      title: row || "null"
    };
  });
  const receivers = [...new Set(data.map(row => row.receiver))].map(row => {
    return {
      groupName: "Receivers",
      type: "receiver",
      title: row || "null"
    };
  });
  const option2 = [...donors, ...receivers];

  const [myTempVal, setMyTempVal] = React.useState([]);

  return (
    <Autocomplete
      open
      multiple
      value={myTempVal}

      disableCloseOnSelect
      disablePortal
      renderTags={() => null}
      noOptionsText="No labels"
      renderOption={(option, { selected }) => {
        return (
          <>
            <Checkbox
            onClick={
              ()=>{
                if(myTempVal.filter(obj=>obj.title===option.title).length!==0){
                  setMyTempVal([...myTempVal.filter(obj=>obj.title!==option.title)],console.log(myTempVal))
                }else{
                  setMyTempVal([...myTempVal.filter(obj=>obj.title!==option.title),option],console.log(myTempVal))
                }

              }
            }
              icon={icon}
              checkedIcon={checkedIcon}
              style={{ marginRight: 8 }}
              checked={myTempVal.filter(obj=>obj.title===option.title).length!==0}
            />
            {option.title}
          </>
        );
      }}
      options={option2}
      // groupBy={option => option.groupName}
      getOptionLabel={option => option.title}
      renderInput={params => (
        <div>
          <div>
            <SearchIcon />
          </div>
          <TextField
            variant="outlined"
            fullWidth
            ref={params.InputProps.ref}
            inputProps={params.inputProps}
          />
        </div>
      )}
    />
  );
};
export default App;

答案 2 :(得分:0)

回答这个问题为时已晚,但可能会对某人有所帮助。

在代码中,您已在自动完成功能中添加了onChange事件。当您单击复选框时,它将触发2次,一次为复选框,另一次为自动完成。因此,第二次触发使复选框再次处于未选中状态,因此您可以在控制台中获取值,但复选框仍为空。

您可以在renderOption中删除您的复选框,并使用复选框中已选中和未选中的图标。

renderOption={(option, { selected }) => {
        return (
           <React.Fragment>
            {selected ? <CheckedIcon> : <uncheckedIcon>}
            <div>
            {option.title}
            </div>
           </React.Fragment>
          </>
        );
      }}