React中State对象未更新,数据库始终存储默认值求助
问题解决:React Formik下拉选单无法更新categoryId状态
核心问题分析
- 选项值不匹配:你把
<option>的value设成了item.category_name,但后端需要的是categoryId(数字类型),导致提交时传的是分类名称而非ID。 - 覆盖Formik默认事件:自定义的
updateDropdown方法覆盖了Formik的默认onChange逻辑,Formik内部的表单状态根本没更新,所以始终提交初始值1。 - 冗余状态:
selectedIndex属于冗余状态,Formik会自动管理表单的选中值,不需要额外维护。
修复步骤
- 修正选项value:把
<option>的value改成分类对应的ID(假设你的category对象里有id或categoryId字段,根据实际接口返回调整)。 - 移除自定义onChange:删掉
updateDropdown方法和Field上的onChange属性,让Formik自动处理状态更新。 - (可选)如需监听选中变化:如果要在选值变化时做额外逻辑,要在自定义onChange里调用Formik的
handleChange。
修改后的关键代码片段
// 移除selectedIndex状态和updateDropdown方法 // ... <Field as="select" name="categoryId"> {listOfCategories.map((item, index) => ( // 这里假设category对象的ID字段是id,根据你的实际接口返回调整成item.categoryId或其他 <option value={item.id} key={index}> {item.category_name} </option> ))} </Field> // 移除selectedIndex相关的渲染代码
完整修正后的CreatePost.jsx
import React, { useContext, useEffect, useState } from "react"; import { Formik, Form, Field, ErrorMessage } from "formik"; import * as Yup from "yup"; import axios from "axios"; import { useNavigate } from "react-router-dom"; import { AuthContext } from "../helpers/AuthContext"; function CreatePost() { const { authState } = useContext(AuthContext); const [listOfCategories, setListOfCategories] = useState([]); const [initialValues, setInitialValues] = useState({ title: "", post: "", ingredients: "", image: "", categoryId: 1, }); let navigate = useNavigate(); useEffect(() => { if (!localStorage.getItem("accessToken")) { navigate("/login"); } axios.get("http://localhost:3001/categories").then((response) => { setListOfCategories(response.data); }); }, []); const validationSchema = Yup.object().shape({ title: Yup.string().required("You must input a Title!"), post: Yup.string().required(), ingredients: Yup.string().required(), }); const onSubmit = (data) => { axios .post("http://localhost:3001/posts", data, { headers: { accessToken: localStorage.getItem("accessToken") }, }) .then((response) => { navigate("/"); }); } return ( <div className="createPostPage"> <Formik initialValues={initialValues} onSubmit={onSubmit} validationSchema={validationSchema} > <Form className="formContainer"> <label>Title: </label> <ErrorMessage name="title" component="span" /> <Field autocomplete="off" id="inputCreatePost" name="title" placeholder="(Ex. Title...)" /> <label>Post: </label> <ErrorMessage name="post" component="span" /> <Field autocomplete="off" id="inputCreatePost" name="post" placeholder="(Ex. Post...)" /> <label>ingredients: </label> <ErrorMessage name="ingredients" component="span" /> <Field autocomplete="off" id="inputCreatePost" name="ingredients" placeholder="(Ex. ingredients...)" /> <Field as="select" name="categoryId"> {listOfCategories.map((item, index) => ( // 注意:这里的item.id要根据你后端返回的category字段调整,比如item.categoryId <option value={item.id} key={index}> {item.category_name} </option> ))} </Field> <button type="submit"> Create Post</button> </Form> </Formik> </div> ); } export default CreatePost;
额外说明
如果确实需要在下拉选单变化时执行自定义逻辑(比如打印选中值),可以通过Formik的useFormikContext获取handleChange,或者在Field的onChange里调用:
// 在Formik组件内部先获取formik对象 const formik = useFormikContext(); // 然后修改Field组件 <Field as="select" name="categoryId" onChange={(e) => { // 先调用Formik的handleChange更新状态 formik.handleChange(e); // 再执行自己的逻辑 console.log("选中的ID:", e.target.value); }} />
内容的提问来源于stack exchange,提问作者asdsd
相关产品推荐
相关产品推荐

