React.js 使用嵌套的 fieldArrays 发送 formData

Posted

技术标签:

【中文标题】React.js 使用嵌套的 fieldArrays 发送 formData【英文标题】:React.js Send formData with nested fieldArrays 【发布时间】:2021-09-24 07:39:06 【问题描述】:

所以我面临一个问题,我试图将表单数据发送到我的 REST-api (spring-boot)。如果我通过邮递员发送我的请求,一切都会按预期进行。我发送的请求: my post request with postman

虽然在前端我使用 react-hook-form,但如果我记录数据,一切似乎都在那里,并且看起来与我从邮递员发送的 JSON 相同,但是我不断收到 415 不支持的 mediaType,或者500 内部服务器错误,取决于我尝试发送嵌套数组的方式。到目前为止,我无法找到类似的问题。

我写的代码:

const handleSubmit, register,control, formState: errors = useForm(mode: 'onBlur');
const 
    fields: ingredientFields,
    append: ingredientAppend,
    remove: ingredientRemove,
 = useFieldArray(control, name: "ingredients");
const 
    fields: directionFields,
    append: directionAppend,
    remove: directionRemove
 = useFieldArray(control, name: "directions",)


const formData = new FormData();
async function onSubmit(data) 
    try 
        setLoading(true)
        formData.append("file", data.file[0]);
        formData.append("title", data.title);
        formData.append("description", data.description);
        formData.append("country", data.country);
        formData.append("cookingTime", data.cookingTime);
        formData.append("calories", data.calories);
        formData.append("beef", data.beef);
        formData.append("fish", data.fish);
        formData.append("pork", data.pork);
        formData.append("lamb", data.lamb);
        formData.append("vegan", data.vegan);
        formData.append("vegetarian", data.vegetarian);
        formData.append("spicy", data.spicy);
        formData.append("poultry", data.poultry)
        formData.append("username", user.username);
        formData.append("userCountry", user.country);
        // // formData.append("ingredients", data.ingredients)
        // const ingredientJson = JSON.stringify(data.ingredients)
        // formData.append("ingredients", ingredientJson)
        // JSON.stringify(data)
        // console.log(data.ingredients)
        // // console.log(ingredientJson)
        // console.log(data)
        // console.log(formData)

        const response = await axios.post('http://localhost:8080/api/recipes',
            
              // formData,
                data
            
        )
        setLoading(false)
        history.push("/recipe-uploaded");
     catch (e) 
        console.error("Something went wong" , e);
    


return (
    <div className="page-wrapper">
        <div className="page-wrapper-inner">
            <h1>Add your recipe</h1>
            <form onSubmit=handleSubmit(onSubmit) className="new-recipe-form">
                step === 1 && (
                    <div className="file-upload">
                        <label className="custom-file-upload">
                            <input type="file" name="file" ...register("file")/>
                            <IoMdCloudUpload className="cloud"/><span>Upload an image</span>
                        </label>
                    </div>
                )
                step === 2 && (
                    <>
                        <label id="titleLabel" htmlFor="title">
                            <input
                                className="textInput"
                                type="text"
                                name="title"
                                id="title"
                                placeholder="Title..."
                                ...register("title",required: true)
                            />
                            errors.title && errors.title.type === "required" && <span className="errorMessage">Required.</span>
                        </label>
                        <label htmlFor="description" id="descriptionLabel">
                            <textarea
                                id="description"
                                name="description"
                                placeholder="Description.."
                                ...register("description", required: true)

                            />
                            errors.description && errors.description.type === "required" && <span className="errorMessage">Required.</span>
                        </label>
                    </>
                )
                step === 3 && (
                    <>
                         ingredientFields.map(( id , index) => 
                            return (
                                <div  key=id>
                                    <div className="ingredient-input-holder">
                                        <label htmlFor=`ingredients[$index].name`>
                                            <input
                                                className="textInput"
                                                type="text"
                                                name=`ingredients[$index].name`
                                                ...register(`ingredients[$index].name`)
                                            />
                                        </label>
                                        <Button
                                            type="button"
                                            classNameButton="btn remove"
                                            buttonTitle=<TiDelete />
                                            onClickEvent=() => ingredientRemove(index)
                                        />
                                    </div>
                                </div>
                            );
                        )
                        <Button
                            type="button"
                            classNameButton="btn"
                            onClickEvent=() => ingredientAppend()
                            buttonTitle="Add an ingredient"
                        />
                    </>
                )
                step === 4 && (
                    <>
                         directionFields.map(( id , index) => 
                            return (
                                <div key=id>
                                    <div className="direction-input-holder">
                                        <label htmlFor=`directions[$index].name`>
                                            <textarea
                                                name=`directions[$index].name`
                                                ...register(`directions[$index].name`)
                                            />
                                        </label>
                                        <Button
                                            type="button"
                                            classNameButton="btn"
                                            buttonTitle=<TiDelete />
                                            onClickEvent=() => directionRemove(index)
                                        />
                                    </div>
                                </div>
                            );
                        )
                        <Button
                            type="button"
                            classNameButton="btn"
                            onClickEvent=() => directionAppend()
                            buttonTitle="Add an directions"
                        />
                    </>
                )
                step === 5 && (
                    <>
                        loading === true ? (
                            <>
                                <label htmlFor="country" className="details">
                                    <input
                                        list="country"
                                        placeholder="Country of origin"
                                        className="textInput"
                                        name="country"
                                        ...register("country", required: true)
                                    />
                                    errors.country && errors.country.type === "required" && <span className="errorMessage">Required.</span>

                                </label>
                                <FlagSelector/>
                                <label htmlFor="cookingTime" className="details">
                                    <input
                                        type="number"
                                        className="textInput"
                                        placeholder="Cooking time in minutes"
                                        name="cookingTime"
                                        ...register("cookingTime", required: true)
                                    />
                                    errors.cookingTime && errors.cookingTime.type === "required" && <span className="errorMessage">Required.</span>

                                </label>
                                <label htmlFor="calories" className="details">
                                    <input
                                        type="number"
                                        className="textInput"
                                        placeholder="Calories"
                                        name="calories"
                                        ...register("calories")
                                    />
                                </label>
                                <div className="checkbox-wrapper">
                                    <div className="checkbox-wrapper-inner">
                                        <label htmlFor="vegetarian">
                                            <input
                                                type="checkbox"
                                                name="vegetarian"
                                                ...register("vegetarian")
                                            /> Vegetarian
                                        </label>
                                        <label htmlFor="vegan">
                                            <input
                                                type="checkbox"
                                                name="vegan"
                                                ...register("vegan")
                                            /> Vegan
                                        </label>
                                        <label htmlFor="beef">
                                            <input
                                                type="checkbox"
                                                name="beef"
                                                ...register("beef")
                                            /> Beef
                                        </label>
                                        <label htmlFor="fish">
                                            <input
                                                type="checkbox"
                                                name="fish"
                                                ...register("fish")
                                            /> Fish
                                        </label>
                                        <label htmlFor="pork">
                                            <input
                                                type="checkbox"
                                                name="pork"
                                                ...register("pork")
                                            /> Pork
                                        </label>
                                        <label htmlFor="lamb">
                                            <input
                                                type="checkbox"
                                                name="lamb"
                                                ...register("lamb")
                                            /> Lamb
                                        </label>
                                        <label htmlFor="poultry">
                                            <input
                                                type="checkbox"
                                                name="poultry"
                                                ...register("poultry")
                                            /> Poultry
                                        </label>
                                        <label htmlFor="spicy">
                                            <input
                                                type="checkbox"
                                                name="spicy"
                                                ...register("spicy")
                                            /> Spicy
                                        </label>
                                    </div>
                                </div>
                            </>
                        ) : (
                            <span>Loading...</span>
                        )
                    </>
                )

                step <= 4 ? (
                    <>
                        <div className="button-wrapper">
                            <Button
                                onClickEvent=() => setStep(step - 1)
                                buttonTitle="Previous step"
                                classNameButton="btn"
                                disabled=step === 1
                                type="button"
                            />
                            <Button
                                onClickEvent=() => setStep(step + 1)
                                buttonTitle="Next step"
                                classNameButton="btn"
                                type="button"
                            />
                        </div>
                    </>
                ) : (
                    <>
                        <div className="button-wrapper submit">
                            <Button
                                onClickEvent=() => setStep(step - 1)
                                buttonTitle="Previous step"
                                classNameButton="btn"
                                disabled=step === 1
                                type="button"
                            />
                            <Button
                                buttonTitle="Save recipe"
                                classNameButton="btn"
                                type="submit"
                            />
                        </div>
                    </>
                )
            </form>
        </div>
    </div>
);

我真的希望这里有人可以帮助我解决这个问题。我觉得我尝试了所有我能找到的东西。

【问题讨论】:

【参考方案1】:

我已经解决了这个问题,原来问题出在我的后端而不是我的前端。

【讨论】:

以上是关于React.js 使用嵌套的 fieldArrays 发送 formData的主要内容,如果未能解决你的问题,请参考以下文章

如何使用嵌套路由和私有路由组件在 react.js 中正确构建路由?

如何在 React Js 中使用 map 实现嵌套循环

当我导航到主包未加载的嵌套路由时使用 React.js 延迟加载

如何使用 redux-form 在不同组件(向上一个组件)中显示 FieldArray 中的字段

如何在 REACT JS API 调用中迭代 JSON 嵌套数组?

如何在 FieldArray 中包含不同值的数组的 yup 验证中添加错误消息?