状态属性未设置[“此字段为必填。”]

时间:2019-03-09 00:46:17

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

我有一个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;
   

1 个答案:

答案 0 :(得分:0)

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

未从输入中收集数据

您不是要从状态收集数据以放入ingredient中。您的代码将创建一个空白ingredient并将其放入数组。

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

您的代码从ingredients中“提取”了this.state.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});
};