Uncaught TypeError: невозможно прочитать свойство then неопределенного React / Redux

Я пытаюсь выполнить запрос на размещение, используя axios, для обновления заданного рецепта аутентифицированным пользователем в базовом API отдыха базы данных. Но у меня есть ошибка в моем коде, говорящая, что «тогда» не определено.

`
 // My updateRecipe.jsx Action file

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

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

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




   }
 }

 export  {
    updateRecipe,
    recipeUpdated,
}`

Это мой файл с редуктором:

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.info(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) блокирует then сразу под 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.info(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.info(this.props.match.params.id);
        this.props.fetchRecipe(this.props.match.params.id)
      }
  }

   handleChangeEvent(event) {
    // this.setState({ [event.target.name] : event.target.value });
    // console.info('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.info(errors)
        this.setState({
            [event.target.name]: event.target.value,
             errors
        })
    }else{
        //console.info(this.state)

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

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

    }
     }

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.info(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.info("see me")
                    this.setState({ done : true, loading: true})},
                (err) => {
                err.response.json()
                .then(({errors}) => {
                    console.info(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.info(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.handleChangeEvent.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.handleChangeEvent.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.handleChangeEvent.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.info(props.match.recipe)
   if (props.match.params.id){
   //console.info(props.match.params.id)
   let recipe = {}
   const recipes = state.recipes.filter(item => {
    //console.info(item)
    //console.info(state.recipes)
    if (item.id == props.match.params.id){
        recipe = item
    }
   })
        //console.info(recipe)
    return {
        recipe
    }  

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

 export default connect(mapStateToProps, { saveRecipe, fetchRecipe }) 
 (RecipeForm);
Поведение ключевого слова "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) для оценки ваших знаний,...
0
0
201
1

Ответы 1

Это должен быть просто updateRecipe, а не this.props.updateRecipe. Вы импортируете updateRecipe() (как функцию) в верхней части компонента <RecipeForm/>. Таким образом, компоненту передается не свойство, а просто функция, которую вы импортировали в этот файл.

Спасибо за ответ! Я сделал то, что ты сказал. Но у меня новая ошибка. `Uncaught TypeError: this.updateRecipe не является функцией` .. Быстрый вопрос, функция, которую я предполагаю вызвать, есть ли это функция из моего действия updateRecipe? потому что это то, что я делаю ...

val15 22.05.2018 11:05

Woops извините, это должен быть просто updateRecipe, а не this.updateRecipe, ха-ха. Поскольку функция updateRecipe не связана с компонентом, это просто импортированная функция. Я обновлю свой ответ

Jayce444 22.05.2018 11:07

Я не уверен, что именно вам следует звонить. Мне сложно сказать, потому что я не знаю точно, что вы пытаетесь сделать, а в вашем вопросе много кода. У вашего компонента <RecipeForm/> даже нет рендера, поэтому я не уверен, какова ваша общая цель, но Stack Overflow обычно больше занимается конкретными проблемами. Если у вас есть общие вопросы о том, как структурировать код и компоненты React / Redux, то документация и примеры будут вашим лучшим выбором, а если у вас есть конкретные проблемы / ошибки, вы можете опубликовать их здесь :)

Jayce444 22.05.2018 11:14

Только что сделал это сейчас, но это сгенерировало ошибку нового типа ... Uncaught TypeError: (0, _updateRecipe.updateRecipe) (...). Then is not a function.

val15 22.05.2018 11:22

Я считаю, что это может быть способ экспорта диспетчера действий updateRecipe(). Хотя внутри этой функции он имеет доступ к .then(), я не уверен, что вы можете добавить к нему .then() при вызове в другом месте. Хотя я признаю, что не совсем уверен в причине этой ошибки, и я не совсем понимаю вашу общую настройку React / Redux здесь (возможно, потому, что она не оптимальна, или, может быть, из-за моего незнания). Надеюсь, что кто-то другой, лучше знакомый с Redux и асинхронным кодом, сможет вам в этом помочь. Простите! :( Я буду следить за этим постом и помогу, если смогу

Jayce444 22.05.2018 11:32

Кроме того, ваш файл updateRecipe.jsx не является JSX, это просто Javascript. Так что это должен быть просто updateRecipe.js. JSX - это смесь HTML / JS, специфичная для React, тогда как действия и редукторы в Redux - это просто Javascript.

Jayce444 22.05.2018 11:35

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