【问题标题】:Thunk Fetch is Undefined When Called from React Component从 React 组件调用时未定义 Thunk Fetch
【发布时间】:2021-03-29 23:56:17
【问题描述】:

我正在玩一个从表单提交调用的 Thunk 函数,但不得不停止,因为 fetch 在组件内部返回 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: ''
    }

    handleChange = (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.handleChange}>
                </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.handleChange}>
                </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。 我什至尝试从动作创建者那里返回一个 Promise,但它不起作用。

【问题讨论】:

    标签: javascript reactjs fetch-api redux-thunk


    【解决方案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 中传递的所有动作创建者都会自动包装在 dispatch 调用中,因此您可以更简洁地将其编写为对象

    const mapDispatchToProps = {
      login,
    }
    

    【讨论】:

    • 他们甚至可以使用简写export default connect(mapStateToProps, {login})
    • 谢谢!我要花一个星期才能找到它
    猜你喜欢
    • 2021-05-21
    • 2017-02-04
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    相关资源
    最近更新 更多