【问题标题】:Properties of state not setting ["This field is required."]未设置状态的属性 [“此字段是必需的。”]
【发布时间】:2019-07-31 01:22:27
【问题描述】:

我有一个 django/react(用于图像上传的 s3 存储桶)项目,它将配方添加到 postgres 数据库。在我的 RecipeFormContainer 组件中,我对配方的属性之一是成分数组。该数组应该填充由单位、数量等键值对组成的对象。我编写了一个名为 addIngredients 的方法,但它似乎没有将对象添加到我的成分数组中。尝试提交我的食谱并发布帖子时,我收到错误“成分:[“此字段是必需的。”]”。请告诉我我所缺少的。 代码如下:

import React, {Component} from 'react';
import {Form} from 'react-bootstrap'
import Button from 'react-bootstrap/Button';


class RecipeFormContainer extends Component {
    constructor(props) {
        super(props);

        this.state = {
            title: '',
            creator: '',
            mealTime: "",
            prepTime: "",
            cookTime: "",
            image_preview: "",
            servings: "",
            directions: '',
            ingredients: [{
                units: '',
                amounts: '',
                multiples: '',
                quantity: '',
                name: ''
            }],
            image: "",

        };

        this.handleImage = this.handleImage.bind(this);
        this.handleIngredientInput = this.handleIngredientInput.bind(this);
        this.handleAddIngredients = this.handleAddIngredients.bind(this);
    }

    handleAddIngredients =(e) => {
        e.preventDefault();

// the ingredients properties are not being added to the ingredients array property on state *************************

        let ingredient = {units: '',
                amounts: '',
                multiples: '',
                quantity: '',
                name: ''};

        //save the current state of ingredients array in variable ingredient
        let {ingredients} = this.state.ingredients;
        // add the ingredient object into the ingredients array ( which is a property of state)
        ingredients.push(ingredient);

        // set the new array of ingredients as the state of the property ingredients
        this.setState( {ingredients: ingredients});
    };



    handleInput = (e) => {
        e.preventDefault();
        this.setState({[e.target.name]: e.target.value});

    };


    handleIngredientInput = (e) => {
        e.preventDefault();
        this.setState({[e.target.name]: e.target.value})
    };

    handleImage(event) {
        event.preventDefault();
        // this makes it show up in preview

        let file = event.target.files[0];
        let fileReader = new FileReader();
        fileReader.onloadend = () => this.setState({image_preview:fileReader.result});
        fileReader.readAsDataURL(file);
        this.setState({image:file});
    }



    submitRecipe = (event) => {
        event.preventDefault();
        let recipe = {...this.state};
        console.log('recipe one', this.state);

        let formData = new FormData();

        formData.append("image", this.state.image);
        formData.append('title', this.state.title);
        formData.append("ingredients", this.state.ingredients);
        formData.append("mealTime", this.state.mealTime);
        formData.append("prepTime", this.state.prepTime);
        formData.append("cookTime", this.state.cookTime);
        formData.append("image_Preview", this.state.image_preview);
        formData.append("servings", this.state.servings);
        formData.append("directions", this.state.directions);
        formData.append("creator", this.state.creator);
        // formData.append("units", this.state.ingredients.units);
        // formData.append("amount", this.state.ingredients.amount);
        // formData.append("multiples", this.state.ingredients.multiples);
        // formData.append("quantity", this.state.ingredients.quantity);
        // formData.append("name", this.state.ingredients.name);

        // add line for each property of state


        const conf = {
            method: "POST",
            body: formData,

        };

        fetch('/api/recipe/', conf).then((response) => {

            return response.json();

        }).then((json) => {
            this.props.addRecipe(json);

        });


    };


    render() {


        return (


            <Form onSubmit={this.submitRecipe} encType="multipart/form-data"  >

                <Form.Group onSubmit={event => {event.preventDefault(); }}  >
                    <img src={this.state.image_preview}/>
                    <input className="input" type="file"  onChange={this.handleImage} name="image" />
                </Form.Group>

                <Form.Group controlId="exampleForm.ControlInput1">
                    <Form.Label>Recipe Name</Form.Label>
                    <Form.Control type="text" placeholder="Enter Recipe Name Here"
                                  name="title"
                                  value={this.state.title}
                                  onChange={this.handleInput}/>


                    <Form.Label>Recipe Creator</Form.Label>
                    <Form.Control type="text" placeholder="Enter Your Name Here"
                                  value={this.state.creator}
                                  name="creator"
                                  onChange={this.handleInput}/>

                </Form.Group>

                <Form.Group controlId="exampleForm.ControlSelect1" id="foodType">
                    <Form.Label>Example select</Form.Label>
                    <Form.Control as="select">
                        <option>Breakfast</option>
                        <option>Lunch</option>
                        <option>Dinner</option>
                        <option>Dessert</option>
                        <option>Vegetarian</option>
                    </Form.Control>
                </Form.Group>


                <Form.Control type="text" placeholder="Prep Time" className="midButt"
                              value={this.state.prepTime}
                              name="prepTime"
                              onChange={this.handleInput}/>
                <Form.Control type="text" placeholder="Cook Time" className="midButt"
                              value={this.state.cookTime}
                              name="cookTime"
                              onChange={this.handleInput}/>


                <Form.Group controlId="exampleForm.ControlSelect1" id="foodTemp">
                    <Form.Control as="select">
                        <option>Fahrenheit</option>
                        <option>Celsius</option>
                    </Form.Control>
                </Form.Group>


                <Form.Group>
                    This Recipe Will Make: <Form.Control type="number" placeholder="servings" id="servings" value={this.state.ingredients.servings} onChange={this.handleInput} name="servings" />

                    <Form.Control type="text" placeholder="cookies, loaves, etc." id="loaf" value={this.state.ingredients.multiples} onChange={this.handleIngredientInput} name="multiples"/>

                </Form.Group>

                {this.state.ingredients.map((ingredient, index) => {
                    return (
                        <div key={index}>
                            <Form.Control type="number" placeholder="#" id="numberAmount" value={this.state.ingredients.quantity} onChange={this.handleIngredientInput} name="amount"/>
                            <Form.Control type="text" placeholder="units" id="units" value={this.state.ingredients.units} onChange={this.handleIngredientInput} name="units"/>
                            <Form.Control type="text" placeholder="Ingredient Name" id="name" value={this.state.ingredients.name} onChange={this.handleIngredientInput} name="name"/>
                        </div>
                    );
                })};

                <Button variant="light" onClick = {this.handleAddIngredients}> + </Button>
                {/*/!*will update state with event handler this.state.ingredients, append object to array *!/*/}


                <Form.Group controlId="exampleForm.ControlTextarea1">
                    <Form.Label>Directions</Form.Label>
                    <Form.Control as="textarea" rows="3"
                        value={this.state.directions}
                              name="directions"
                              onChange={this.handleInput}/>
                </Form.Group>


                <Button type="submit" variant="secondary">Save This Recipe !</Button>

            </Form>
        )
    };
}


export default RecipeFormContainer;
   

【问题讨论】:

  • 尝试控制台记录您的this.state.ingredients 并查看添加新成分时的内容。也许结果不是你所期待的
  • 它是空的。我的 handleIngredientInput 方法没有达到我的预期。我不确定使我想要的逻辑正常工作的语法。你有什么建议吗?

标签: javascript django reactjs amazon-s3 react-bootstrap


【解决方案1】:

查看您的代码,您的handleAddIngredients 不正确。你犯了两个错误:

不从输入中收集数据

您没有从州收集数据以放入ingredient。您的代码会创建一个空白 ingredient 以放入数组中。

试图以错误的方式复制ingredients 数组。

您的代码从this.state.ingredients“提取”ingredients,但这是不可能的。你的ingredients 属于你的state,而不是state.ingredients

而不是做

let { ingredients } = this.state.ingredients

你可以这样做

let { ingredients } = this.state

甚至

let ingredients = [ ...this.state.ingredients ]

结论

完成所有修复后,您的代码应如下所示:

handleAddIngredients = (e) => {
     e.preventDefault();

    //Extracting the values from the state
    let { units, amounts, multiples, quantity, name } = this.state

    // Inserting the values into the new ingredient
    let ingredient = { units, amounts, multiples, quantity, name }

    // Creating the copy
    let ingredients = [ ... this.state.ingredients ]

    // add the ingredient object into the ingredients array ( which is a property of state)
    ingredients.push(ingredient);

    // set the new array of ingredients in the state
    this.setState({ingredients});
};

【讨论】:

  • 非常感谢您花时间解释!我知道我的方法不能正常工作,但不知道如何解决它们。我马上试试这个!
  • @ChristinaRoberts,不客气!我建议您检查所有其他句柄是否也按预期工作。
  • 这解决了我能够添加成分的问题,但现在更进一步,发布请求仍然无法正常工作。我对 javascript 非常陌生,并且对事物的反应方面很敏感,因此将我的逻辑(后端样式)转换为有效的 javascript 代码仍然是一个挑战哈哈
  • @ChristinaRoberts,因为此答案解决了您的成分字段为空的问题,请随时将其标记为解决方案。如果还有其他问题,与第一个无关,我建议您提出一个新问题
猜你喜欢
  • 2014-12-15
  • 1970-01-01
  • 1970-01-01
  • 2021-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多