useState tidak memperbarui dengan benar setelah pilihan di dalam dropdown

Saya memiliki fungsi untuk menonaktifkan dropdown hingga pilihan dibuat di 2 dropdown lainnya. Saya yakin itu tidak mengaktifkan dropdown dengan benar karena beberapa masalah asinkron dengan useState.

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

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 = () => {
  if (homeSelect != 'Home' && hedgeSelect != 'Hedge'){
    //enable the symbol dropdown
      setDisabled(false);
  } else {
      //disable the select exchanges dropdown
      setDisabled(true);
  }
}
<FormControl dense>
  <TextField
    id="standard-select-currency"
    select
    label="Home"
    className={classes.textField}
    value={homeSelect}
    onChange={handleHome}
    SelectProps={{
      native: true,
    }}
    helperText="Please select exchange"
  >
    {home.map((option) => (
      <option key={option.value} value={option.value}>
        {option.label}
      </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"
  >
    {hedge.map((option) => (
      <option key={option.value} value={option.value}>
        {option.label}
      </option>
    ))}
  </TextField>
</FormControl>

<FormControl dense>
  <TextField
    id="standard-select-currency"
    select
    label="Symbols"
    className={classes.textField}
    value={symbolSelect}
    onChange={handleSymbol}
    disabled={disabled}
    SelectProps={{
      native: true,
    }}
    helperText="Please select the exchanges"
  >
    {symbols.map((option) => (
      <option key={option.value} value={option.value}>
        {option.label}
      </option>
    ))}
  </TextField>
</FormControl>

Dropdown home dan hedge memerlukan pilihan sebelum mengaktifkan dropdown symbol. Kesalahannya adalah symbol dropdown tidak akan aktif sampai home dan hedge dipilih lebih dari sekali.

Bagaimana cara mengubah metode yang saya gunakan untuk menggunakan useReducer (jika ini akan memperbaiki masalah pembaruan status)? Saya mencoba membacanya tetapi tidak mengerti seperti apa switch case saya.

Bantuan apa pun dihargai, terima kasih.


person Zero Cool    schedule 03.11.2020    source sumber


Jawaban (1)


Operasi yang ditetapkan tidak sinkron. Jadi ketika Anda melakukan ini:

setHomeSelect(event.target.value);
exchange_change();

Saat pemanggilan metode kedua dipanggil, variabel homeSelect tidak berubah. Ini akan berubah ketika logika selesai diproses dan komponen bersiap untuk dirender ulang.

Lebih penting lagi, ini tidak seperti React:

const exchange_change = () => {
  if (homeSelect != 'Home' && hedgeSelect != 'Hedge'){
    //enable the symbol dropdown
    setDisabled(false);
  } else {
    //disable the select exchanges dropdown
    setDisabled(true);
  }
}

Saat Anda mengubah nilai status di sini, secara konseptual Anda tampaknya mencoba mengubah UI. Jangan. Komponen UI hanya bisa merespons keadaan. Jadi, alih-alih menggunakan metode itu, Anda dapat melakukan ini di komponen Simbol Anda:

disabled={homeSelect == 'Home' || hedgeSelect == 'Hedge'}

Jika Anda ingin memasukkannya ke dalam suatu metode, masukkan ke dalam metode yang dipanggil oleh komponen, bukan dipanggil sebelum rendering ulang. Misalnya:

disabled={() => checkSelects()}

Dan cara tersebut bisa berupa:

const checkSelects = () => 
  homeSelect == 'Home' || hedgeSelect == 'Hedge';

Namun secara keseluruhan, perhatikan saja urutan pengoperasiannya di sini. Semua logika yang dipanggil oleh peristiwa UI dijalankan, yang mengantri pembaruan ke status. Kemudian negara bagian diperbarui. Kemudian komponen dirender ulang (bila perlu). Jangan mengandalkan status yang diperbarui selama logika itu.

person David    schedule 03.11.2020
comment
Masuk akal tapi sangat aneh. Mengapa React membaca setHomeSelect(event.target.value); exchange_change(); dan menunggu hingga fungsinya selesai untuk membuat perubahan status? Tampaknya sangat membingungkan bagi pengembang - person Zero Cool; 03.11.2020