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

React中fetch获取数据后传递对象至GuestForm组件为空问题

问题解决步骤

1. 修复Edit组件的状态管理与异步请求

原代码中obj是普通变量,修改它不会触发React组件重新渲染,且fetch异步请求的执行时机错误,导致组件渲染时还没拿到接口返回的数据。修改如下:

import React, { useState, useEffect } from 'react';
import GuestForm from '../../components/Guests/GuestForm.js';
import { useParams } from 'react-router-dom';

function Edit() {
  const { id } = useParams();
  const [mode, setMode] = useState('edit');
  const [successMessage, setsuccessMessage] = useState('The guest has been edited successfully!');
  const [action, setAction] = useState('/guests/edit');
  // 将obj改为React状态变量,确保修改后触发组件重渲染
  const [obj, setObj] = useState({first_name: '', last_name: '', email: '', password: ''});

  const headers = {
    'Content-Type': 'application/json;charset=UTF-8',
    "Accept": "application/json"
  };

  // 用useEffect包裹异步请求,确保组件挂载/依赖变化时仅执行一次
  useEffect(() => {
    fetch(process.env.REACT_APP_API_URL + action, {
      method: 'POST',
      headers: headers,
      body: JSON.stringify({data: {id: id}}),
    })
    .then((response) => response.json())
    .then((responseJson) => {
      // 更新状态,将接口返回的用户数据填充到obj中
      setObj({
        first_name: responseJson.json.guest.first_name,
        last_name: responseJson.json.guest.last_name,
        email: responseJson.json.guest.email,
        password: '' // 密码留空,避免返回敏感数据
      });
    })
    .catch((error) => {
      console.error(error);
    });
  }, [id, action]); // 依赖id和action,确保参数变化时重新请求

  return (
    <>
      <div className="container">
        {/* 传递setObj给子组件,用于同步表单输入变化 */}
        <GuestForm mode={mode} successMessage={successMessage} obj={obj} action={action} setObj={setObj} />
      </div>
    </>
  );
}

export default Edit;

2. 修复GuestForm组件的状态同步问题

原GuestForm用props的初始值初始化内部state,之后props更新时不会同步,且提交时用的是原始props的obj,不是用户修改后的表单值。修改为受控组件,直接依赖父组件的状态:

import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import { Button, Form } from "react-bootstrap";
import axios from "axios";
import { toast } from 'react-toastify';

function GuestForm({mode, successMessage, obj, action, setObj}) {
  const history = useHistory();
  const [details, setDetails] = useState([]);
  const [loading, setLoading] = useState(false);

  // 统一处理输入变化,同步更新父组件的obj状态
  const handleInputChange = (field, value) => {
    setObj(prevState => ({...prevState, [field]: value}));
  };

  const handleSave = e => {
    e.preventDefault();
    setLoading(true);
    axios({
      method: "POST",
      url: process.env.REACT_APP_API_URL + action,
      headers: { 
        'Content-Type': 'application/json;charset=UTF-8',
        "Accept": "application/json" 
      },
      data: {
        data: obj // 使用最新的obj数据提交
      }
    }).then(result => {
      if(!result.data.json.error) {
        toast(successMessage, {
          position: "top-right",
          autoClose: 5000,
          hideProgressBar: false,
          closeOnClick: true,
          pauseOnHover: true,
          draggable: true,
          progress: undefined,
        });
        history.push('/dashboard/guests');
      }
      setDetails(result.data.json);
      setLoading(false);
    }).catch(err => {
      console.error(err);
      setLoading(false);
    });
  };

  return (
    <>
      <div className="container">
        <div className="row">
          <div className="col-lg-12">
            <h1 className="mt-0 mb-4 green-color">{mode === 'edit' ? 'Edit' : 'New'} Guest</h1>
          </div>
        </div>

        <Form onSubmit={handleSave} autoComplete="off">
          <div className="row">
            <div className="col-xs-12 col-sm-6 col-md-6 col-lg-6 mt-2">
              <Form.Group>
                <label htmlFor="exampleInputEmail1">Email Address</label>
                <Form.Control
                  value={obj.email} 
                  onChange={e => handleInputChange('email', e.target.value)}
                  type="email"
                  autoComplete="off"
                />
              </Form.Group>
            </div>
            <div className="col-xs-12 col-sm-6 col-md-6 col-lg-6 mt-2">
              <Form.Group>
                <label>Password</label>
                <Form.Control
                  value={obj.password} 
                  onChange={e => handleInputChange('password', e.target.value)}
                  type="password"
                  autoComplete="new-password"
                />
              </Form.Group>
            </div>
          </div>
          <div className="row">
            <div className="col-xs-12 col-sm-6 col-md-6 col-lg-6 mt-2">
              <Form.Group>
                <label>First Name</label>
                <Form.Control
                  value={obj.first_name} 
                  onChange={e => handleInputChange('first_name', e.target.value)}
                  type="text"
                  autoComplete="off"
                />
              </Form.Group>
            </div>
            <div className="col-xs-12 col-sm-6 col-md-6 col-lg-6 mt-2">
              <Form.Group>
                <label>Last Name</label>
                <Form.Control
                  value={obj.last_name} 
                  onChange={e => handleInputChange('last_name', e.target.value)}
                  type="text"
                  autoComplete="off"
                />
              </Form.Group>
            </div>
          </div>
          
          {(details.guest && details.error) && <div className="error-message mt-4 mb-1">{details.message}</div>}

          <Button
            className="btn-fill pull-right mt-3"
            type="submit"
            variant="info"
            disabled={loading}
          >
            {loading ? `${mode === 'edit' ? 'SAVE CHANGES' : 'ADD'}...` : (mode === 'edit' ? 'SAVE CHANGES' : 'ADD')}
          </Button>
          <div className="clearfix"></div>
        </Form>
      </div>
    </>
  );
}

export default GuestForm;

关键修改说明

  • Edit组件:将obj转为React状态变量,用useEffect控制异步请求的执行时机,请求完成后通过setObj更新状态,触发组件重新渲染,确保GuestForm能拿到最新的用户数据。
  • GuestForm组件:改为受控组件,直接使用父组件传递的obj作为表单值,输入变化时同步更新父组件状态,确保数据实时同步;提交时直接使用最新的obj数据,避免提交过时的初始值。

内容的提问来源于stack exchange,提问作者Brian Millot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 21:45:35