можно ли написать асинхронный код в обратном вызове setState

#reactjs

#reactjs

Вопрос:

Можете ли вы написать асинхронный код в обратном вызове setState. Я пытаюсь реализовать проверку формы на уровне поля. Я хочу вызвать метод проверки после того, как метод onChange установил состояние в новое значение.

Я получил все, чтобы правильно работать с yup и его методом validateSync. Синхронный код работает правильно. Но в последнее время я подумал о повторной реализации логики, чтобы сделать код проверки асинхронным и использовать метод yup validate (async). Но после того, как он заработал и вернул значение после проверки, когда я пытаюсь установить состояние, возвращая новые значения, похоже, это ничего не делает.

код выглядит примерно так ->

edit -> setState обратный вызов вызывает validateFormField (извините, я понял, я пропустил некоторый код при попытке упростить его

 this.state = {
  formElements: [{}, {}, {}]    //array of objects having fields name, value, err, etc
}
handleChange(() => {
  this.setState(prevState => {
    //logic for updating the value
    return {formElements: newFormElements}
  }, () => {
    const formElements = this.state.formElements;
    validateFormField(fieldName);
  })
)

validateFormField(fieldName) {
  this.setState(prevState => {
    /*
      validateField -> Async function that has yup.validate which returns null
      in try block
      and throws error in the catch block with the formElements object updated
      with validation values
    */
    return validateField(fieldName)
      .then(() => {
      /* 
        expected behaviour up till this point and since there is nothing
        updated, I return null so as to tell react not to update the state
      */
      return null;
    })
    .catch(newFormElements => {
      /*
        expected behaviour untill this point and since formElements object
        is updated, I return the new object, so as to tell react to update
        the state with the new value
      */
      return {formElements: newFormElements};
     })
   })
 }
  


Также у меня есть два дополнительных вопроса, которые связаны с вышеупомянутым вопросом:

1> Есть ли какие-либо недостатки в использовании асинхронных проверок? Поскольку метод React setState также является асинхронным, это может вызвать неожиданное поведение, поскольку может возникнуть условие гонки. Как и в onChange, вызывает setState для следующего изменения значения до завершения асинхронного кода предыдущей проверки, в результате чего React выдает ошибку проверки, даже если новое значение является действительным.

2> Есть ли какие-либо недостатки в использовании проверок синхронизации? Причина, по которой я пытался реализовать логику асинхронной проверки, даже когда моя синхронизация работает отлично, заключается в том, что я слышал, что лучше всего использовать асинхронный код, когда это возможно, особенно для тяжелой работы, такой как проверка. Поскольку тяжелая проверка может привести к тому, что единственный поток будет занят, и ничто другое не сможет быть выполнено в этом цикле событий.

Комментарии:

1. Асинхронный код в этом случае не имеет смысла. На какую выгоду вы надеетесь?

2. @AlexMckay Как я указал в пункте 2, я подумал, что это будет лучше для производительности, поскольку это не будет блокировать цикл событий. Хотя я не совсем уверен, для меня имело смысл попытаться это сделать. Кроме того, я подумал, что была причина, по которой библиотека yup имела функцию асинхронной проверки. В любом случае, я надеюсь, что кто-нибудь укажет, что асинхронность не нужна, и даст вескую причину для этого, поскольку у меня уже есть рабочий код для проверки синхронизации. И я использую debounce, чтобы не вызывать его при каждом обмене.

3. асинхронная проверка не имеет смысла. Кто бы ни сказал вам, что лучше всего использовать async, это совершенно неправильно. Проверка также не является тяжелой работой. Это не более нескольких выражений регулярных выражений.

4. Вы должны стремиться оптимизировать свое приложение React только тогда, когда заметите, что оно замедляется, и вы делаете это с помощью профилировщика. Попытка ранней оптимизации с помощью асинхронных проверок является пустой тратой вашего времени и даже не ускоряет работу вашего приложения, а на самом деле с большей вероятностью замедлит работу вашего приложения.

5. @AlexMckay Согласился с несколькими и простыми полями, но в некоторых случаях регулярное выражение может быть очень дорогим, и для многих полей с четными проверками даты я не знаю. Кроме того, причина, по которой я впервые пошел с проверкой синхронизации, заключалась в том, что я хотел, чтобы это было своего рода блокировкой, поскольку я имел смысл. Но недавно я перешел на materail-ui и начал использовать его элементы формы, и мне показалось, что блокирующий код делает мой material-ui не гладким. Поскольку я думал, что проверка блокировки синхронизации препятствует выполнению mui, я попробовал асинхронный подход, чтобы увидеть разницу.

Ответ №1:

Вот как я бы это сделал.

 doSomethingSync(state) {
// ...
}
async doSomethingAsync(state) {
// ...
}

handleChange(() => {
  this.setState(prevState => {}, () => {
  doSomethingSync(state)
  doSomethingAsync(state).then().catch()
}