Я пытаюсь выполнить запрос на размещение, используя 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);



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Это должен быть просто updateRecipe, а не this.props.updateRecipe. Вы импортируете updateRecipe() (как функцию) в верхней части компонента <RecipeForm/>. Таким образом, компоненту передается не свойство, а просто функция, которую вы импортировали в этот файл.
Woops извините, это должен быть просто updateRecipe, а не this.updateRecipe, ха-ха. Поскольку функция updateRecipe не связана с компонентом, это просто импортированная функция. Я обновлю свой ответ
Я не уверен, что именно вам следует звонить. Мне сложно сказать, потому что я не знаю точно, что вы пытаетесь сделать, а в вашем вопросе много кода. У вашего компонента <RecipeForm/> даже нет рендера, поэтому я не уверен, какова ваша общая цель, но Stack Overflow обычно больше занимается конкретными проблемами. Если у вас есть общие вопросы о том, как структурировать код и компоненты React / Redux, то документация и примеры будут вашим лучшим выбором, а если у вас есть конкретные проблемы / ошибки, вы можете опубликовать их здесь :)
Только что сделал это сейчас, но это сгенерировало ошибку нового типа ... Uncaught TypeError: (0, _updateRecipe.updateRecipe) (...). Then is not a function.
Я считаю, что это может быть способ экспорта диспетчера действий updateRecipe(). Хотя внутри этой функции он имеет доступ к .then(), я не уверен, что вы можете добавить к нему .then() при вызове в другом месте. Хотя я признаю, что не совсем уверен в причине этой ошибки, и я не совсем понимаю вашу общую настройку React / Redux здесь (возможно, потому, что она не оптимальна, или, может быть, из-за моего незнания). Надеюсь, что кто-то другой, лучше знакомый с Redux и асинхронным кодом, сможет вам в этом помочь. Простите! :( Я буду следить за этим постом и помогу, если смогу
Кроме того, ваш файл updateRecipe.jsx не является JSX, это просто Javascript. Так что это должен быть просто updateRecipe.js. JSX - это смесь HTML / JS, специфичная для React, тогда как действия и редукторы в Redux - это просто Javascript.
Спасибо за ответ! Я сделал то, что ты сказал. Но у меня новая ошибка. `Uncaught TypeError: this.updateRecipe не является функцией` .. Быстрый вопрос, функция, которую я предполагаю вызвать, есть ли это функция из моего действия updateRecipe? потому что это то, что я делаю ...