Асинхронный / ожидающий избыточный поток не возвращает обещание к действию правильно - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть thunk, использующий Axios, который отправляет на экспресс-маршрут с использованием Sequelize.

Маршрут отправляется правильно (т. Е. Данные добавляются в БД), но действие внутри компонента React не выполняется 'ведет себя как ожидалось.Используя async/await, я ожидаю, что действие подождет, пока оно не завершит запись базы данных, прежде чем продолжить, но здесь это не так.Я получаю undefined от действия.

Группа отправляет действие по экспресс-маршруту, где я отправляю действие, чтобы обновить свое хранилище редуксов и возвращаю ответ:

const addedNewList = (newList) => ({type: ADD_NEW_LIST, newList})

export const addNewList = (name, userId) => async dispatch => {
  try {
    const { data } = await axios.post('/api/list/add', { name, userId })
    dispatch(addedNewList(data))
    return data
  } catch (err) {
    console.error(err)
  }
}

Использованиеотладчик, я могу подтвердить, что return data фактически возвращает ответ от сервера, который мне нужен.Я также могу подтвердить, что магазин приставок обновляется корректно.

Но здесь, когда я пытаюсь получить доступ к данным ответа как result, я получаю undefined:

  handleSubmit = async () => {
    const result = await this.props.addNewList(this.state.name, this.props.userId)

    // ** result is 'undefined' **

    this.handleClose()

    // pass off the results
  }

Если я добавлю setTimeout после того, как вызову addNewList действие, оно работает, как ожидалось.Это говорит мне о том, что, возможно, это не возвращает обещание?Но я понимаю, что если вы вернете ответ от сервера в thunk, он сделает это.

Для полноты, вот мой маршрут, который я также подтвердил с помощью отладчика, что данные передаются, как ожидалось:

const userAuth = function(req, res, next) {
  if (req.isAuthenticated()) {
    return next()
  }
  res.status(401).send('Unauthorized user')
}

router.post('/add', userAuth, async (req, res, next) => {
  const { name, userId } = req.body
  try {
    const list = await List.create({ name, userId })
    res.json(list)
  } catch(err) { next(err) }
})

Почему действие возвращает undefined в методе handleSubmit?

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Ответ Александра направил меня в нужное русло, поэтому я поделюсь своим решением на случай, если оно кому-нибудь поможет (как он предложил).

Хотя я мог бы продолжить пытаться решить эту проблему, обернувотправка в Promise, лучшее решение было переосмыслить, как компонент был структурирован.

В моей ситуации я хотел получить идентификатор для вновь созданной строки в базе данных, чтобы я мог передать ее в history.push.

  handleSubmit = async () => {
    const result = await this.props.addNewList(this.state.name, this.props.userId)

    this.handleClose()

    history.push(`/list/${result.id}`)
}

с возвращением resultundefined, URL не обновлялся правильно.

Лучшим решением было получить доступ к новым данным из хранилища избыточных данных, где они были обновлены.Таким образом, я мог быть уверен, что история не будет обновлена, пока данные не будут готовы.

Таким образом, мой обновленный компонент теперь выглядел примерно так, где история не будет обновляться до тех пор, пока не будет newId:

  handleSubmit = () => {
    this.props.addNewList(this.state.name, this.props.userId)
    this.handleClose()
  }

  render(){
    const { newId } = this.props

    if (newId) { 
      history.push(`/list/${newId}`)
    }

   return (
      ....
   )
  }
}

const mapStateToProps = (state) => {
  return {
    newId: state.list.newId
  }
}

Вместо того, чтобы поместить это в рендер, я мог бы также использовать метод жизненного цикла компонента, такой как componentWillReceiveProps или аналогичный.

0 голосов
/ 15 ноября 2018

Попробуйте вместо этого вернуть dispatch из addedNewList(data):

export const addNewList = (name, userId) => async dispatch => {
  try {
    const { data } = await axios.post('/api/list/add', { name, userId })
    return Promise.resolve(dispatch(addedNewList(data)));
  } catch (err) {
    console.error(err)
  }
}

При этом можно подумать о реструктуризации компонента, чтобы вместо него использовать mapStateToProps для использования значений / result из обновленногоХранить Redux вместо того, чтобы явно ожидать ответа и вручную передавать значение?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...