未捕获的TypeError:无法读取未定义的React / Redux的属性'then'

时间:2018-05-22 08:14:30

标签: javascript reactjs redux

我正在尝试使用axios来执行put请求,以便由数据库基本rest API中的经过身份验证的用户更新给定的Recipe。但是我的代码中有一个错误,说'then'是未定义的。

`
 // My updateRecipe.jsx Action file

  import axios from 'axios';
  export const RECIPE_UPDATED = "RECIPE_UPDATED"

  const recipeUpdated = (recipe) => {
  //console.log(recipe)
     return {
       type: RECIPE_UPDATED,
       recipe
           }
      }

   const updateRecipe = (data) => {
      return dispatch => {
         // console.log(data)
         // console.log(dataid)
         axios.put(`http://localhost:8009/api/v1/recipes/${data.id}`, data)
         .then(() => dispatch(
             //console.log(data),
             recipeUpdated(data)
    )).catch( error => {
        //console.log(error.message)
        error} )




   }
 }

 export  {
    updateRecipe,
    recipeUpdated,
}`

这是我的Reducer文件:

import { SET_RECIPES } from '../action/recipeAction.jsx';
import { RECIPE_FETCH } from '../action/RecipeFetch.jsx'
import { RECIPE_UPDATED } from '../action/updateRecipe.jsx'

export default function recipes(state = [], action = {}) {
switch(action.type) { 

    case RECIPE_UPDATED:
      return state.map(item => {
          //console.log(item)
          if(item.id === action.recipe.id) return action.recipe;
          return item;
      })

    case RECIPE_FETCH: 
    const index = state.findIndex(item => item.id === action.recipe.id);
    if(index > -1){
        return state.map(item => {
            if(item.id === action.recipe.id) return action.recipe;
            return item;
        });
    }else{
        return [
            ...state,
            action.recipe
        ];
    }

    case SET_RECIPES: return action.recipes;
    default: return state; 
   }
}

这是我的组件文件,这是我遇到问题的地方,在我的if(id)块中,然后就在this.props.updatedRecipe下面。

    import React from 'react';
    import PropTypes from 'prop-types';
    import classnames from 'classnames';
    import { connect } from 'react-redux';
    import { Redirect } from 'react-router-dom';
    import { Alert } from 'reactstrap';
    import { saveRecipe, fetchRecipe, updateRecipe } from 
     '../../action/index.jsx'
    import styles from './style.js'

  class RecipeForm extends React.Component {
   constructor (props) {
      super(props)
       this.state = {
            id: this.props.recipe ? this.props.recipe.id : null,
            title: this.props.recipe ? this.props.recipe.title : '',
            description: this.props.recipe ? this.props.recipe.description : 
        '',
            imageUrl: this.props.recipe ? this.props.recipe.imageUrl : '',
            errors:{},
            loading: false,
            done: false,
         }
     }

    componentWillReceiveProps (nextProps){
       //console.log(nextProps.recipe)
    this.setState({
        id: nextProps.recipe.id,
        title: nextProps.recipe.title,
        description: nextProps.recipe.description,
        imageUrl: nextProps.recipe.imageUrl,

       })
    }

    componentDidMount ()  {
        if(this.props.match.params.id){
        //console.log(this.props.match.params.id);
        this.props.fetchRecipe(this.props.match.params.id)
      }
  }

   handleChange(event) {
    // this.setState({ [event.target.name] : event.target.value });
    // console.log('updatedRecipe: ' + event.target.id + ' == '+ 
     event.target.value )
    if (!!this.state.errors[event.target.name]){
        let errors = Object.assign({}, this.state.errors);
        delete errors[event.target.name];
        // console.log(errors)
        this.setState({
            [event.target.name]: event.target.value,
             errors
        })
    }else{
        //console.log(this.state)

        this.setState({
               [event.target.name]: event.target.value,

        // let handleChange = Object.assign({}, this.state);
        // handleChange[event.target.id] = event.target.value;
        // this.setState({
        //     recipes: handleChange,
    })    

    }
     }

handleSubmit(e){
    e.preventDefault();

    let errors = {};
    if (this.state.title === '') errors.title = "Can't be empty";
    if (this.state.description === '') errors.description = "Can't be 
      empty";
    if (this.state.imageUrl === '') errors.imageUrl = "Can't be empty";

    this.setState({ 
        errors 
    })
    const isValid = Object.keys(errors).length === 0

    if(isValid){
        const { id, title, description, imageUrl } = this.state;
        //console.log(this.state)
        this.setState({ loading: true });
        if(id){

            this.props.updateRecipe({ id, title, description, imageUrl })
             // this is where the BUG is COMING FROM
            .then(
                ()=>{
                    console.log("see me")
                    this.setState({ done : true, loading: true})},
                (err) => {
                err.response.json()
                .then(({errors}) => {
                    console.log(errors)
                    this.setState({
                    errors})
                }
                )
            }
            )
        }else{
            this.props.saveRecipe({ title, description, imageUrl, })
        .then(
            ()=>{
                this.setState({ done : true, loading: true})},
            (err) => {
            err.response.json()
            .then(({errors}) => {
                console.log(errors)
                this.setState({
                errors})
            }
            )
        }
        )
        }

    }


}

 render() {
    const form = (

        <div className="d-flex justify-content-center align-items-center 
      container">
        <form className={classnames({ loading: this.state.loading })}>
        <h1 style={styles.header}>Add New Recipe</h1>


        {!!this.state.errors.form && <Alert color="danger"> 
     {this.state.errors.form }</Alert>}
          <div className="form-group row">
            <div className="form-group col-md-12 col-md-offset-8 text- 
      right">
            <div className={classnames('field', { error: 
       !!this.state.errors.title})}>
                <label htmlFor="title">Recipe Title</label>
                <input 
                name="title" 
                value={this.state.title} 
                onChange={this.handleChange.bind(this)}
                className="form-control" 
                id="title" 
                placeholder="title"/>
                <span style={{color: "#ae5856"}} >{this.state.errors.title} 
     </span>
            </div>
            <div className={classnames('field', { error: 
      !!this.state.errors.description})}>

                <label htmlFor="title">Recipe Description</label>
                <input 
                name="description" 
                value={this.state.description} 
                onChange={this.handleChange.bind(this)}
                className="form-control" 
                id="description" 
                placeholder="description"/>
               <span style={{color: "#ae5856"}}> 
      {this.state.errors.description}</span>
            </div>
            <div className={classnames('field', { error: 
           !!this.state.errors.imageUrl})}>

                <label htmlFor="imageUrl">Recipe Image</label>
                <input 
                name="imageUrl" 
                value={this.state.imageUrl}
                onChange={this.handleChange.bind(this)}  
                className="form-control" 
                id="imageUrl" 
                placeholder="Image"/>
               <span style={{color: "#ae5856"}}>{this.state.errors.imageUrl} 
          </span>
            </div>
            <div>
                {this.state.imageUrl !== '' && <img src= 
         {this.state.imageUrl} alt="" className="img-rounded"/>}
            </div>
            <button onClick={this.handleSubmit.bind(this)} type="submit" 
   className="btn btn-primary">Submit</button>
            </div>
            </div>
      </form>
      </div>
    );


    return (

       <div>
           {this.state.done ? <Redirect to="/recipes"/> : form} 
       </div>


       )
    }
 }
 RecipeForm.propTypes = {
    saveRecipe: PropTypes.func.isRequired,

 }

function mapStateToProps(state, props){
   //console.log(props.match.recipe)
   if(props.match.params.id){
   //console.log(props.match.params.id)
   let recipe = {}
   const recipes = state.recipes.filter(item => {
    //console.log(item)
    //console.log(state.recipes)
    if (item.id == props.match.params.id){
        recipe = item
    }
   })
        //console.log(recipe)
    return {
        recipe
    }  

    //console.log(recipe);
  }
   return { recipe: null };
 }

 export default connect(mapStateToProps, { saveRecipe, fetchRecipe }) 
 (RecipeForm);

1 个答案:

答案 0 :(得分:0)

应该是updateRecipe,而不是this.props.updateRecipe。您正在updateRecipe()组件的顶部导入<RecipeForm/>(作为函数)。因此,它不是传递给组件的属性,它只是您在该文件中导入的函数。