设置状态不会更新下拉复选框-使用挂钩

时间:2019-10-14 19:56:07

标签: javascript reactjs

我是新来的人,我正在建立一个网站,用户可以在其中通过复选框下拉列表选择特定类别(又名jurisdiction),并在搜索栏中输入query

我的亲子关系是:

Searchform (parent)
     Dropdown (child of Searchform)
     Searchbar (child of Searchform)

我的seachbar工作正常。 (How to pass state from child to parent with Hooks

但是

我无法使Dropdown工作。 特别是:

  • 所有复选框均已选中(不应该如此)
  • setJurisdicitons无法正常工作,因为它console.log()Choose...一词,而不是我实际检查的东西。每当我按下表单中的submit按钮时,就会发生这种情况。

enter image description here

搜索表单

 function Searchform() {
     function handleSubmit() {
       console.log(query);
       console.log(jurisdictions)
     }

     const [query, setQuery] = useState('');
     const [jurisdictions, setJurisdictions] = useState(["Choose..."]);

     const onChangeQuery = useCallback(
       event => setQuery(event.target.value),
       [],
     );

     const onChangeDropdown = useCallback(
       event => setJurisdictions(event.target.value),
       [],
     );

     return(
       <form onSubmit={handleSubmit}>
         <div className="searchbar-dropdown">
           <div className="searchbar">
           <Searchbar value={query} onChange={onChangeQuery} />
           </div>
           <div className="dropdown">
             <Dropdown value={jurisdictions} onChange={onChangeDropdown}/>
           </div>
         </div>
         <Button variant="contained" color="primary" type="submit">
           Submit your search
         </Button>
       </form>
     )
   }



   export default Searchform;

Dropdown.js

const jurisdictions_list = [
  'Jurisdiction 1',
  'Jurisdiction 2',
  'Jurisdiction 3',
  'Jurisdiction 4',
  'Jurisdiction 5',
];



function Dropdown({ value, onChange }) {
  const classes = useStyles();
  const theme = useTheme();
  console.log("trytrytry")

  console.log(value)
  const handleChange = event => {
    console.log(value);
  };


  return (
    <div className={classes.root}>
      <FormControl className={classes.formControl}>
        <InputLabel htmlFor="select-multiple-checkbox">Jurisdiction</InputLabel>
        <Select
          multiple
          value={value}
          onChange={onChange, handleChange}
          input={<Input id="select-multiple-checkbox" />}
          renderValue={selected => selected.join(', ')}
          MenuProps={MenuProps}
        >
          {jurisdictions_list.map(jurisdiction_element => (
            <MenuItem key={jurisdiction_element} jurisdiction={jurisdiction_element}>
              <Checkbox checked={jurisdiction_element.indexOf(jurisdiction_element) > -1} />
              <ListItemText primary={jurisdiction_element} />
            </MenuItem>
          ))}
        </Select>
      </FormControl>
    </div>
  );
}


export default Dropdown;

2 个答案:

答案 0 :(得分:1)

组件的简约版本

SelectableDropdown使用Set实例在内部跟踪选定的项目,并仅将选定的项目通知给父项(请注意,SelectableDropdown是不受控制的组件,您需要再添加几行代码以使其成为受控组件)

function Searchbar(props) {
  
  function handleChange(ev) {
    props.onChange && props.onChange(ev.target.value);
  }
  
  return (
    <label className="Searchbar">
      Search 
      <input 
        type="text" 
        value={props.value}
        onChange={handleChange}
      />
    </label>
  )
}

function SelectableDropDown(props) {
  const [selectedOpts, setSelectedOpts] = React.useState(new Set());
  
  function handleChange(ev) {
    const value = ev.target.value;
    const checked = ev.target.checked;
    
    if (checked) {
      selectedOpts.add(value);
    } else {
      selectedOpts.delete(value);
    }
    
    setSelectedOpts(new Set(selectedOpts));
    props.onChange && props.onChange(Array.from(selectedOpts.values()));
  }
  
  return (
    <fielset className="SelectableDropDown">
      {props.options.map((opt) => (
        <label key={opt}>
          {opt} 
          <input 
            type="checkbox" 
            name="opts" 
            value={opt}
            onChange={handleChange}
          />
        </label>
      ))}
    </fielset>
  )
}

const OPTIONS = [
  'Jurisdiction 1',
  'Jurisdiction 2',
  'Jurisdiction 3',
  'Jurisdiction 4',
  'Jurisdiction 5',
];

function App() {
  const [query, setQuery] = React.useState('');
  const [selectedOptions, setSelectedOptions] = React.useState([]);
  
  function handleSubmit(ev) {
    ev.preventDefault();
    console.log('submitting');
    console.log(query);
    console.log(selectedOptions);
    console.log('submitting end');
  }
  
  function handleQueryChange(newQuery) {
    setQuery(newQuery);
  }
  
  function handleOptionsChange(newSelectedOptions) {
    setSelectedOptions(newSelectedOptions);
  }
  
  return (
    <form onSubmit={handleSubmit}>
      <Searchbar 
        value={query}
        onChange={handleQueryChange}
      />
      <div>
        <SelectableDropDown 
          options={OPTIONS}
          onChange={handleOptionsChange}
        />
      </div>
      <div>
        <button>Search</button>
      </div>
    </form>
  );
}


ReactDOM.render(
  <App />,
  document.getElementById('app')
);
.Searchbar,
.SelectableDropDown label {
  display:block;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>
</head>
<body>
 <div id="app"></div>
</body>
</html>

答案 1 :(得分:0)

<Checkbox checked={jurisdiction_element.indexOf(jurisdiction_element) > -1} />

如果jurisdiction_element包含jurisdiction_element,则会选中该复选框。该条件将始终评估为true,因此将始终选中您的复选框。

您似乎打算使用:

<Checkbox checked={value.indexOf(jurisdiction_element) > -1} />

此外,您无法通过执行<Select onChange={onChange, handleChange} />来设置两个回调函数。您需要选择一个。如果您想同时使用两者,则让一个函数调用另一个函数或创建一个新函数同时调用这两个函数:

const handleChange = event => {
    onChange(event);
    console.log(value);
}

// or
<Select onChange={event => { onChange(event); handleChange(event); }} />