Thunk Fetch не определен при вызове из компонента React

Я играл с функцией Thunk, вызываемой из отправки формы, но мне пришлось остановиться, потому что выборка возвращает undefined внутри компонента и не запускает .then (). Я не могу понять почему, я упростил Thunk до его ядра, но все равно не повезло. У меня такой же шаблон с другой формой в том же приложении, и он работает плавно. Бэкэнд отвечает правильно.

// actions/users.actions.js
export const login = (formData) => {
  return (dispatch) => {
    return fetch("http://localhost:3001/login", {
      method: "POST",
      headers: {"Content-Type": "application/json"},
      body: JSON.stringify(formData)
    }).then(res => res.json())
  }
}
// containers/LoginForm.js
import React, { Component } from 'react'
import { connect } from "react-redux";
import { Link } from 'react-router-dom'
import { login } from '../actions/users.actions'

class LoginForm extends Component {

    state = {
      username: '',
      password: ''
    }

    handleChangeEvent = (e) => {
      this.setState({
        ...this.state,
        [e.target.name]: e.target.value
      })
    }

    fetchOnSubmit = (e) => {
      e.preventDefault()
      this.props.login(this.state) 
//=> at this point it says TypeError: Cannot read property 'then' of undefined
        .then(res => this.props.errors ? null : this.props.history.push(`/`))
    }

    render() {
        return (
          <form onSubmit = {this.fetchOnSubmit}>
            { this.props.alert.message &&
              <div className = {`alert ${this.props.alert.type}`}>
                {this.props.alert.message.split('<b>').splice(0,1)}
                <b>{this.props.alert.message.split('<b>').splice(1,1)}</b>
              </div>
            }
            <h2 className='text-dark mb-4'>Login{'  '}
              {this.props.submitting && 
                <img alt = "spinner" src = "data:image/gif;...." />
              }
            </h2>
            <div>
              <fieldset className='ml-auto mr-auto w-100'>
                <label htmlFor = "username" className = "block">
                  Username*
                  <span className = "text-red-400"></span>
                </label>
                <input
                  type = "text"
                  name = "username"
                  className='w-100 border border-primary shadow p-2 mb-4 rounded'
                  onChange = {this.handleChangeEvent}>
                </input>
              </fieldset>
            </div>
            <div>
              <fieldset className='ml-auto mr-auto w-100'>
                <label htmlFor = "password" className = "block">
                  Password*
                  <span className = "text-red-400"></span>
                </label>
                <input
                  type = "password"
                  name = "password"
                  className='w-100 border border-primary shadow p-2 mb-4 rounded-3 rounded'
                  onChange = {this.handleChangeEvent}>
                </input>
              </fieldset>
            </div>
            <div class = "row mb-5 ml-2 mr-2 mt-3">
                <div class = "col-8 d-flex"><button className='h-1 border-0 rounded-pill ml-auto mr-auto' 
                  style = {{width:'100%',display:'inline'}} type='Submit'>Login</button></div>
                <div class = "col-4 d-flex">
                  <Link to = "/Signup" className='ml-auto mr-auto mt-auto mb-auto text-primary hardlink'>Register</Link>
                </div>
            </div>
          </form>
        )
    }
}

const mapStateToProps = state => {
  return {
    submitting: state.sessions.submitting,
    alert: state.alert,
    errors: state.sessions.errors
  }
}

const mapDispatchToProps = dispatch => {
  return {
    login: (credentials) => {
      dispatch(login(credentials))
    }
  }
}

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

Как мне избежать появления ошибки TypeError: Cannot read property 'then' of undefined. Я даже пытался вернуть обещание от создателя действия, но это не сработало.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
38
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема

Похоже, что анонимная функция в вашем mapDispatchToProps является недействительным возвратом. Вы объявили область действия функции и ничего не вернули.

const mapDispatchToProps = dispatch => {
  return {
    login: (credentials) => {
      dispatch(login(credentials))
      // <-- nothing returned here
    }
  }
}

Решение

Вернуть отправленное действие

const mapDispatchToProps = dispatch => {
  return {
    login: (credentials) => {
      return dispatch(login(credentials));
    }
  }
}

или используйте неявный возврат стрелочной функции

const mapDispatchToProps = dispatch => {
  return {
    login: (credentials) => dispatch(login(credentials)),
  }
}

и поскольку все создатели действий, переданные в mapDispatchToProps, автоматически заключаются в вызов диспетчеризации, вы можете записать его еще более кратко как объект

const mapDispatchToProps = {
  login,
}

Они могли даже использовать сокращение export default connect(mapStateToProps, {login})

Linda Paiste 30.03.2021 04:08

Благодарность! мне бы потребовалась неделя, чтобы найти это

user3755529 31.03.2021 12:13

Другие вопросы по теме