You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用后端数据回填React Formik表单实现库存项编辑

React+Formik实现库存条目编辑:数据回填与更新

一、获取后端数据并初始化表单值

在组件挂载时,通过Axios请求后端接口获取目标条目数据,用useState存储数据,useEffect触发请求:

import { useEffect, useState } from 'react';
import axios from 'axios';
import { useParams, useNavigate } from 'react-router-dom';

const EditBoxForm = () => {
  const [boxData, setBoxData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const { boxId } = useParams(); // 从路由获取要编辑的条目ID
  const navigate = useNavigate();

  useEffect(() => {
    const fetchBoxData = async () => {
      try {
        const response = await axios.get(`/api/boxes/${boxId}`); // 替换成你的后端接口
        setBoxData(response.data);
        setIsLoading(false);
      } catch (error) {
        console.error('获取数据失败:', error);
        setIsLoading(false);
      }
    };
    fetchBoxData();
  }, [boxId]);

  // 加载状态处理
  if (isLoading) return <div>加载中...</div>;
  if (!boxData) return <div>无法获取条目数据</div>;

  // 后续代码...
}

二、动态设置Formik初始值

把写死的initialValues替换成后端返回的boxData,确保字段一一对应:

<Formik
  validationSchema={schema}
  initialValues={{
    name: boxData.name || "",
    numberOfSets: boxData.numberOfSets || "0",
    sortValue: boxData.sortValue || "0",
    boxType: boxData.boxType || "",
    price: boxData.price || "",
    photo: boxData.photo || "",
  }}
  // 修改提交逻辑为更新操作
  onSubmit={({ name, numberOfSets, sortValue, boxType, price, photo }) => {
    boxService.updateBox(boxId, name, numberOfSets, sortValue, boxType, price, photo); // 调用更新接口
    alert("Box更新成功!");
    navigate('/boxes'); // 跳转到列表页替代刷新
  }}
>

三、修正表单拼写错误

你的代码里存在两处拼写问题,会导致表单值异常:

  • Form.Item的name属性写成了sortVlaue,需改为sortValue
  • 错误提示误用了errors?.numberOfBoxes,需改为errors?.sortValue

修正后的Sort Value字段:

<Form.Item name="sortValue" label="Sort Value">
  <Input
    name="sortValue"
    type="number"
    value={values.sortValue}
    onChange={(e) => setFieldValue("sortValue", e.target.value)}
    onBlur={handleBlur}
    placeholder="Please enter sorting value"
  />
  {errors?.sortValue && touched?.sortValue && (
    <Text type="danger">{errors?.sortValue}</Text>
  )}
</Form.Item>

四、完整修改后的组件代码

import { useEffect, useState } from 'react';
import axios from 'axios';
import { useParams, useNavigate } from 'react-router-dom';
import { Formik, Form } from 'formik';
import { Input, Select, Button, Text } from 'antd';
import Dropzone from 'react-dropzone';

const EditBoxForm = () => {
  const [boxData, setBoxData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const { boxId } = useParams();
  const navigate = useNavigate();

  useEffect(() => {
    const fetchBoxData = async () => {
      try {
        const response = await axios.get(`/api/boxes/${boxId}`);
        setBoxData(response.data);
        setIsLoading(false);
      } catch (error) {
        console.error('获取数据失败:', error);
        setIsLoading(false);
      }
    };
    fetchBoxData();
  }, [boxId]);

  if (isLoading) return <div>加载中...</div>;
  if (!boxData) return <div>无法获取条目数据</div>;

  const schema = ...; // 你的表单校验规则
  const dropStyle = {
    border: '2px dashed #ccc',
    borderRadius: '4px',
    padding: '20px',
    textAlign: 'center',
    cursor: 'pointer',
  };

  return (
    <Formik
      validationSchema={schema}
      initialValues={{
        name: boxData.name || "",
        numberOfSets: boxData.numberOfSets || "0",
        sortValue: boxData.sortValue || "0",
        boxType: boxData.boxType || "",
        price: boxData.price || "",
        photo: boxData.photo || "",
      }}
      onSubmit={({ name, numberOfSets, sortValue, boxType, price, photo }) => {
        boxService.updateBox(boxId, name, numberOfSets, sortValue, boxType, price, photo);
        alert("Box更新成功!");
        navigate('/boxes');
      }}
    >
      {({ values, errors, touched, handleBlur, handleSubmit, setFieldValue }) => {
        return (
          <Form name="edit-gift" onFinish={handleSubmit} labelAlign="left">
            <Form.Item name="name" label="Name">
              <Input
                name="name"
                title="Product Name"
                dataIndex="name"
                key="productName"
                value={values.name}
                onChange={(e) => setFieldValue("name", e.target.value)}
                onBlur={handleBlur}
                placeholder="Please enter Box Name"
              />
              {errors?.name && touched?.name && (
                <Text type="danger">{errors?.name}</Text>
              )}
            </Form.Item>

            <Form.Item name="numberOfSets" label="Number of Sets">
              <Input
                name="numberOfSets"
                type="number"
                value={values.numberOfSets}
                onChange={(e) => setFieldValue("numberOfSets", e.target.value)}
                onBlur={handleBlur}
                placeholder="Please enter Number of Sets"
              />
              {errors?.numberOfSets && touched?.numberOfSets && (
                <Text type="danger">{errors?.numberOfSets}</Text>
              )}
            </Form.Item>

            <Form.Item name="sortValue" label="Sort Value">
              <Input
                name="sortValue"
                type="number"
                value={values.sortValue}
                onChange={(e) => setFieldValue("sortValue", e.target.value)}
                onBlur={handleBlur}
                placeholder="Please enter sorting value"
              />
              {errors?.sortValue && touched?.sortValue && (
                <Text type="danger">{errors?.sortValue}</Text>
              )}
            </Form.Item>

            <Form.Item name="boxType" label="Type">
              <Select
                value={values.boxType}
                onChange={(value) => setFieldValue("boxType", value)}
                onBlur={handleBlur}
                placeholder="Please enter Box Type"
              >
                <Select.Option value="reward">Reward</Select.Option>
                <Select.Option value="doublerandom">Double Random</Select.Option>
              </Select>
              {errors?.boxType && <Text type="danger">{errors?.boxType}</Text>}
            </Form.Item>

            <Form.Item name="price" label="Price">
              <Input
                name="price"
                title="Product Price"
                dataIndex="price"
                key="price"
                value={values.price}
                onChange={(e) => setFieldValue("price", e.target.value)}
                onBlur={handleBlur}
                placeholder="Please enter Box Price"
              />
              {errors?.price && touched?.price && (
                <Text type="danger">{errors?.price}</Text>
              )}
            </Form.Item>

            <Form.Item name="photo" label="Product Picture">
              <div className="dropzone-container">
                {values.photo && <img src={values.photo} alt="Product" />}
                {!values.photo && (
                  <Dropzone
                    onDrop={(acceptedFiles) => {
                      const fr = new FileReader();
                      fr.onload = () => {
                        setFieldValue("photo", fr.result);
                        setFieldValue("imgName", acceptedFiles[0].name);
                      };
                      fr.readAsDataURL(acceptedFiles[0]);
                    }}
                    accept={{ "image/*": [] }}
                    maxSize={1000000}
                  >
                    {({ getRootProps, getInputProps }) => (
                      <section>
                        <div {...getRootProps({ style: dropStyle })}>
                          <input {...getInputProps()} />
                          <p>Drag 'n' drop some files here, or click to select files</p>
                          <aside>
                            Tips: The size ratio of the photo is: 750:216,
                            the maximum recommended size is 1M, and the format is: .jpg, .jpeg, .png
                          </aside>
                        </div>
                      </section>
                    )}
                  </Dropzone>
                )}
              </div>
            </Form.Item>

            <Form.Item>
              <Button type="primary" htmlType="submit">Confirm save</Button>
            </Form.Item>
          </Form>
        );
      }}
    </Formik>
  );
};

export default EditBoxForm;

注意事项

  • 确保后端返回字段名与表单initialValues字段完全匹配
  • 自行实现boxService.updateBox方法,调用后端更新接口并传入条目ID
  • 优先使用路由导航替代页面刷新,提升用户体验
  • 如果图片为后端存储文件,需确保返回的是可直接访问的URL

内容的提问来源于stack exchange,提问作者Hammad Yousaf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 14:55:27