简体   繁体   English

React 中的多个复选框过滤

[英]Multiple checkbox filtering in React

I'm struggling to create multiple Checkbox filtering in React with Material-UI.我正在努力使用 Material-UI 在 React 中创建多个复选框过滤。 The difficult is that checkbox options are created dynamically from received data and should be split by each type of Select components困难在于复选框选项是根据接收到的数据动态创建的,并且应该由每种类型的 Select 组件拆分

But I can't properly create states to manage them in the App.但我无法在 App 中正确创建状态来管理它们。

Any ideas how to do it correctly?任何想法如何正确地做到这一点?

Options Component选项组件

function filterDuplicate(arr) {
  return arr.filter((elem, index, array) => array.indexOf(elem) === index);
}

export default function Options({ stat }) {
  const [form, setForm] = useState({
    publicationType: "",
    termType: "",
    reportGroup: "",
    reportState: "",
    reportFormat: ""
  });

  const publicationTypes = filterDuplicate(
    stat.map((data) => data.publicationType)
  );
  const termTypes = filterDuplicate(stat.map((data) => data.termType));
  const reportGroups = filterDuplicate(stat.map((data) => data.reportGroup));
  const reportStates = filterDuplicate(stat.map((data) => data.reportState));
  const reportFormats = filterDuplicate(stat.map((data) => data.reportFormat));

  function handleSubmit(e) {
    e.preventDefault();
    console.log(form);
  }

  return (
    <>
      <form onSubmit={handleSubmit} className="options">
        <Select type="Publication type" options={publicationTypes} />
        <Select type="Term type" options={termTypes} />
        <Select type="Report group" options={reportGroups} />
        <Select type="Status" options={reportStates} />
        <Select type="File Type" options={reportFormats} />
        <Button variant="contained" color="secondary" type="submit">
          RESET
        </Button>
      </form>
    </>
  );
}

Options.propTypes = {
  stat: PropTypes.arrayOf(PropTypes.shape({})).isRequired
};

Select Component Select 组件

export default function Select({ type, options }) {
  const [check, setCheck] = useState([]);
  const [value, setValue] = useState("");

  const classes = useStyles();

  const handleChange = (e) => {
    if (e.target.checked) {
      setCheck([...check, e.target.value]);
    } else {
      setCheck(check.filter((id) => id !== e.target.value));
    }
    const str = check.join(", ");
    setValue(str);
  };

  return (
    <>
      <FormControl className={classes.formControl}>
        <InputLabel id="select-label" className={classes.label}>
          {type}
        </InputLabel>
        <MaterialSelect labelId="select-label" id="input-select">
          {options.map((option) => (
            <Checkbox option={option} key={option} onChange={handleChange} />
          ))}
        </MaterialSelect>
      </FormControl>
    </>
  );
}

Checkbox Component复选框组件

const Checkbox = React.forwardRef(({ option, onChange }, ref) => {
  return (
    <div ref={ref}>
      <FormControlLabel
        control={<MaterialCheckbox onChange={onChange} color="primary" />}
        label={option}
        value={option}
      />
    </div>
  );
});

Checkbox.propTypes = {
  option: PropTypes.string.isRequired,
  onChange: PropTypes.func.isRequired
};

export default Checkbox;

https://codesandbox.io/s/checkbox-filter-vqex7?file=/src/Options.js:0-1593 https://codesandbox.io/s/checkbox-filter-vqex7?file=/src/Options.js:0-1593

The problem is you only pass data from parent to child.问题是您只将数据从父母传递给孩子。 On App.js they are two separate components.在 App.js 上,它们是两个独立的组件。 You should write a function on App.js that connects these two components.您应该在连接这两个组件的 App.js 上编写 function。

Your App.js你的 App.js

export default function App() {
  const [stat, setState] = useState([]);

  useEffect(() => {
    setState(data);
  }, []);

  return (
    <div className="App">
      <div>
        <div>
          <h1>Information</h1>
        </div>
        <Options stat={stat} />
        <Data info={stat} />
      </div>
    </div>
  );
}

App.js when filtering method added添加过滤方法时的 App.js

export default function App() {
  const [stat, setState] = useState([]);

  useEffect(() => {
    setState(data);
  }, []);
  const handleFilter = (selectedValue) => {
    console.log(selectedValue);
   //apply filtering here and setState again
  }
  return (
    <div className="App">
      <div>
        <div>
          <h1>Information</h1>
        </div>
        <Options stat={stat} handleFilter={handleFilter} />
        <Data info={stat} />
      </div>
    </div>
  );
}

Options.js选项.js

export default function Options({ stat, handleFilter }) {
  const [form, setForm] = useState({
    publicationType: "",
    termType: "",
    reportGroup: "",
    reportState: "",
    reportFormat: ""
  });

  const publicationTypes = filterDuplicate(
    stat.map((data) => data.publicationType)
  );
  const termTypes = filterDuplicate(stat.map((data) => data.termType));
  const reportGroups = filterDuplicate(stat.map((data) => data.reportGroup));
  const reportStates = filterDuplicate(stat.map((data) => data.reportState));
  const reportFormats = filterDuplicate(stat.map((data) => data.reportFormat));

  function handleSubmit(e) {
    e.preventDefault();
    console.log(form);
  }

  return (
    <>
      <form onSubmit={handleSubmit} className="options">
        <Select
          type="Publication type"
          options={publicationTypes}
          handleFilter={handleFilter}
        />
        <Select
          type="Term type"
          options={termTypes}
          handleFilter={handleFilter}
        />
        <Select
          type="Report group"
          options={reportGroups}
          handleFilter={handleFilter}
        />
        <Select
          type="Status"
          options={reportStates}
          handleFilter={handleFilter}
        />
        <Select
          type="File Type"
          options={reportFormats}
          handleFilter={handleFilter}
        />
        <Button variant="contained" color="secondary" type="submit">
          RESET
        </Button>
      </form>
    </>
  );
}

Select.js Select.js

export default function Select({ type, options, handleFilter }) {
  const [check, setCheck] = useState([]);
  const [value, setValue] = useState("");

  const classes = useStyles();

  const handleChange = (e) => {
    if (e.target.checked) {
      handleFilter(e.target.value);
      setCheck([...check, e.target.value]);
    } else {
      setCheck(check.filter((id) => id !== e.target.value));
    }
    const str = check.join(", ");
    setValue(str);
  };

  return (
    <>
      <FormControl className={classes.formControl}>
        <InputLabel id="select-label" className={classes.label}>
          {type}
        </InputLabel>
        <MaterialSelect labelId="select-label" id="input-select">
          {options.map((option) => (
            <Checkbox option={option} key={option} onChange={handleChange} />
          ))}
        </MaterialSelect>
      </FormControl>
    </>
  );
}

With that structure, you can receive checked value on App.js and filter data.使用该结构,您可以在 App.js 上接收检查值并过滤数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM