第三个下拉菜单基于前 2 个下拉菜单的选择,但第三个下拉菜单的状态总是落后 1 步

3rd dropdown is based off first 2 dropdown's selections but the 3rd's state is always 1 step behind

我有以下代码:

const [homeSelect, setHomeSelect] = useState('Home');
const [hedgeSelect, setHedgeSelect] = useState('Hedge');
const [symbolSelect, setSymbolSelect] = useState('');
const [similarSymbols, setSimilarSymbols] = useState([]);

const handleHome = (event) => {
    setHomeSelect(event.target.value);
    exchange_change();
  };

const handleHedge = (event) => {
    setHedgeSelect(event.target.value);
    exchange_change();
};

const handleSymbol = (event) => {
    setSymbolSelect(event.target.value);
};

const exchange_change = () => {
    setSimilarSymbols([]);
    //add symbols together from selected dropdowns
    var allSymbols = response.content.symbols[homeSelect] + response.content.symbols[hedgeSelect];
    console.log(allSymbols);

    //sort the symbols
    allSymbols = allSymbols.split(",");
    var sort_arr = allSymbols.sort();
    console.log(sort_arr);

    //find duplicates
    for(var i = 0; i < sort_arr.length-1; i++)
    {
      if(sort_arr[i + 1] == sort_arr[i]) { 
        setSimilarSymbols(similarSymbols => [...similarSymbols, sort_arr[i]]);
      }
    }
  }

<FormControl dense>
    <TextField
      id="standard-select-currency"
      select
      label="Home"
      className={classes.textField}
      value={homeSelect}
      onChange={handleHome}
      SelectProps={{
        native: true,
      }}
      helperText="Please select exchange"
    >
      <option>Home</option>
      {response ? response.content.exchanges.map((option) => (
        <option value={option}>
          {option}
        </option>
      )) : <option>Data is loading...</option>}
    </TextField>
  </FormControl>

  <FormControl dense>
    <TextField
      id="standard-select-currency"
      select
      label="Hedge"
      className={classes.textField}
      value={hedgeSelect}
      onChange={handleHedge}
      SelectProps={{
        native: true,
      }}
      helperText="Please select exchange"
    >
      <option>Hedge</option>
      {response ? response.content.exchanges.map((option) => (
        <option value={option}>
          {option}
        </option>
      )) : <option>Data is loading...</option>}
    </TextField>
  </FormControl>

  <FormControl dense>
    <TextField
      id="standard-select-currency"
      select
      label="Symbols"
      className={classes.textField}
      value={symbolSelect}
      onChange={handleSymbol}
      disabled={homeSelect == 'Home' || hedgeSelect == 'Hedge'}
      SelectProps={{
        native: true,
      }}
      helperText="Please select the exchanges"
    >
      <option>Symbol</option>
      {console.log(similarSymbols.map((element) => (element)))}
      {response ? similarSymbols.map((option) => (
        <option value={option}>
          {option}
        </option>
      )) : <option>Data is loading...</option>}
    </TextField>
  </FormControl>

homeSelecthedgeSelect 被 selected 之后,'similarSymbols' 应该填充相应的数据。

问题是,'similarSymbols' 在 homeSelecthedgeSelect 再次 select 之后才会正确填充,例如,select 一个下拉菜单和 select 另一个下拉菜单,然后再 select 其中一个。

好像状态落后了 1 步,我不知道如何让它工作。

感谢任何帮助,谢谢。

这是setState的async造成的,也是hook造成的

调用 exchange_change 时,状态尚未设置,并且选择了以前的值。

尝试使用 useEffect 来响应对 homeSelecthedgeSelect 的更改:

const [homeSelect, setHomeSelect] = useState('Home');
const [hedgeSelect, setHedgeSelect] = useState('Hedge');
const [symbolSelect, setSymbolSelect] = useState('');
const [similarSymbols, setSimilarSymbols] = useState([]);


const handleHome = (event) => {
    setHomeSelect(event.target.value);
  };

const handleHedge = (event) => {
    setHedgeSelect(event.target.value);
};

const handleSymbol = (event) => {
    setSymbolSelect(event.target.value);
};
React.useEffect(exchange_change, [homeSelect, hedgeSelect]) // Here you listen to changes and update similarSymbols once changes are made.

const exchange_change = () => {
    setSimilarSymbols([]);
    //add symbols together from selected dropdowns
    var allSymbols = response.content.symbols[homeSelect] + response.content.symbols[hedgeSelect];
    console.log(allSymbols);

    //sort the symbols
    allSymbols = allSymbols.split(",");
    var sort_arr = allSymbols.sort();
    console.log(sort_arr);

    //find duplicates
    for(var i = 0; i < sort_arr.length-1; i++)
    {
      if(sort_arr[i + 1] == sort_arr[i]) { 
        setSimilarSymbols(similarSymbols => [...similarSymbols, sort_arr[i]]);
      }
    }
  }

<FormControl dense>
    <TextField
      id="standard-select-currency"
      select
      label="Home"
      className={classes.textField}
      value={homeSelect}
      onChange={handleHome}
      SelectProps={{
        native: true,
      }}
      helperText="Please select exchange"
    >
      <option>Home</option>
      {response ? response.content.exchanges.map((option) => (
        <option value={option}>
          {option}
        </option>
      )) : <option>Data is loading...</option>}
    </TextField>
  </FormControl>

  <FormControl dense>
    <TextField
      id="standard-select-currency"
      select
      label="Hedge"
      className={classes.textField}
      value={hedgeSelect}
      onChange={handleHedge}
      SelectProps={{
        native: true,
      }}
      helperText="Please select exchange"
    >
      <option>Hedge</option>
      {response ? response.content.exchanges.map((option) => (
        <option value={option}>
          {option}
        </option>
      )) : <option>Data is loading...</option>}
    </TextField>
  </FormControl>

  <FormControl dense>
    <TextField
      id="standard-select-currency"
      select
      label="Symbols"
      className={classes.textField}
      value={symbolSelect}
      onChange={handleSymbol}
      disabled={homeSelect == 'Home' || hedgeSelect == 'Hedge'}
      SelectProps={{
        native: true,
      }}
      helperText="Please select the exchanges"
    >
      <option>Symbol</option>
      {console.log(similarSymbols.map((element) => (element)))}
      {response ? similarSymbols.map((option) => (
        <option value={option}>
          {option}
        </option>
      )) : <option>Data is loading...</option>}
    </TextField>
  </FormControl>