Действие Redux и функции async / await имеют разное поведение в компоненте класса и функционале

#javascript #reactjs #redux #react-redux

#javascript #reactjs #redux #реагировать-redux

Вопрос:

Я работал над Next.js приложение с этими зависимостями:

 "react": "^16.9.0",
"react-redux": "^5.0.7",
"redux": "^4.0.4",
  

Одним из моих действий redux, которое создает stepsNameThatMustBeShown (свойство состояния redux), является:

 export const setInitialSteps = () => {
     //.....
     // some codes that creates the stepsNameThatMustBeShown array
     //....
    return {
        type: ActionTypes.SET_QUICK_RESUME_GENERATOR_MODAL_INITIAL_STEPS,
        data: stepsNameThatMustBeShown
    }
};
  

И я использовал этот фрагмент в двух разных местах моего приложения, в компоненте класса и функциональном компоненте.

 <button onClick = {
    async () => {
      await this.props.setInitialSteps();
      if (this.props.stepsNameThatMustBeShown.length > 1) {
        this.props.setCurrentStep(this.props.stepsNameThatMustBeShown[0]);                                                               
        this.props.setQuickResumeDisplayStatus(true);                                                                    
        this.props.setUnUpdatedStepsName([...this.props.stepsNameThatMustBeShown]);
      }
    }}>
      Open
</button>
//....
//...


 const mapStateToProps = (state) => {
    return {
        stepsNameThatMustBeShown: state.quickResumeGeneratorModal.stepsNameThatMustBeShown,
    };
};


function mapDispatchToProps(dispatch) {
   return {
            setQuickResumeDisplayStatus: bindActionCreators(setQuickResumeDisplayStatus, dispatch),
            setInitialSteps: bindActionCreators(setInitialSteps, dispatch),
            setCurrentStep: bindActionCreators(setCurrentStep, dispatch),
            setUnUpdatedStepsName: bindActionCreators(setUnUpdatedStepsName, dispatch),
        }
    }

export default connect(mapStateToProps, mapDispatchToProps)(resultTest);
  

Очевидно, что я не использовал this.props в функциональном компоненте. Все эти функции в фрагменте кода являются действиями redux. Во фрагменте кода я обновил свойство состояния redux и использовал его сразу после его обновления.
В компоненте класса ключевые слова async и await работают так, как мы ожидали, но в функциональном компоненте ключевое слово await работает некорректно. Я прочитал некоторые связанные вопросы, которые существуют в этом сообществе, но ни один из них не смог помочь мне решить мою проблему.

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

1. Основываясь на приведенном выше коде, я не вижу ни одного варианта использования async await , возможно, вы слишком много думаете. Попробуйте удалить async await и посмотреть, решит ли это. Вы вызываете this.props.setInitialSteps();` который будет выполняться синхронно и возвращать и выполнять следующую строку в вашем обработчике кликов.

2. функция @Rikin setInitialSteps инициализирует stepsNameThatMustBeShown prop, поэтому мне нужно ее инициализировать, а затем использовать как часть условия оператора if, поэтому я должен использовать функцию await .

3. является ли эта функция stepsNameThatMustBeShown асинхронной? если это так, то используйте await при вызове выполнения, опять же, нет необходимости в await в вашем обработчике кликов.

4. Это не функция, это свойство состояния redux.

5. setInitialSteps является вашим создателем действия (на основе того, что вы показываете). Он не делает ничего, кроме возврата действия с типом действия и вашей полезной нагрузкой data . Вызывая его в своем функциональном компоненте, вы возвращаете только этот объект, вы ничего с ним не делаете. В вашем компоненте класса вы связываете ту функцию, bindActionCreators которая выполняет dispatch для вас, таким образом, она работает. Опять же, ничего общего с async await still на основе того, что вы показали выше.

Ответ №1:

Вам необходимо использовать react-redux 7.1 или более поздней версии для использования const dispatch = useDispatch() в вашем функциональном компоненте, а затем вызвать dispatch() обработчик onClick.

В вашем функциональном компоненте используйте:

 const dispatch = useDispatch()
  

и тогда ваш обработчик будет выглядеть следующим образом:

 <button onClick = {
    async () => {
      const action = this.props.setInitialSteps(); // <======
      dispatch(action); // <=====
      if (this.props.stepsNameThatMustBeShown.length > 1) {
        this.props.setCurrentStep(this.props.stepsNameThatMustBeShown[0]);                                                               
        this.props.setQuickResumeDisplayStatus(true);                                                                    
        this.props.setUnUpdatedStepsName([...this.props.stepsNameThatMustBeShown]);
      }
    }}>
      Open
</button>
  

Опять же, все async то, что у вас есть, здесь не нужно в вашем случае использования.