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

ReactJS中如何在父组件访问子函数组件的状态变量?

问题描述

我正在开发网站,遇到了组件状态变量访问的问题。我有一个Addresses.jsx页面,其中包含地址模态框(AddressModal),模态框的内容由AddressForm组件实现。我希望在AddressModal的onSaveAddress函数中获取AddressForm组件的状态,请问该如何实现?

Addresses.jsx 文件

const Addresses = () => {
const [selectedAddress, setSelectedAddress] = useState();
const [modalType, setModalType] = useState();
const {
  elementRef: addressModalRef,
  show: showAddressModal,
  hide: hideAddressModal,
} = useModal();

return (
  <>
    <div className="bg-light px-3 px-lg-4 py-4">
    <h1 className="h4 mb-4">My Addresses</h1>
    <div className="row g-3">
      <div className="col-12 col-md-6 col-lg-4">
        <AddressButton
          onClick={() => {
            setSelectedAddress(undefined);
            setModalType("NewAddress");
            showAddressModal();
          }}
        />
      </div>
      {ADDRESSES.map((address, i) => (
        <div className="col-12 col-md-6 col-lg-4" key={i}>
          <AddressButton
            {...address}
            onClick={() => {
              setSelectedAddress(address);
              setModalType("EditAddress");
              showAddressModal();
            }}
          />
        </div>
      ))}
    </div>
  </div>

  <AddressModal
    address={selectedAddress}
    elementRef={addressModalRef}
    hide={hideAddressModal}
    modalType={modalType}
  />
</>)};
export default Addresses;

AddressModal 文件

const AddressModal = ({ address, elementRef, hide, modalType }) => {
const onSaveAddress = () => {
  console.log(address);
  hide();
};
return (
<Modal elementRef={elementRef} centered size="lg" fullscreen>
  <ModalBody>
    <AddressForm address={address} /> {/* 我希望在onSaveAddress函数中获取该组件的状态 */}
  </ModalBody>
  <ModalFooter>
    <button
      type="button"
      className="btn btn-primary flex-grow-1 px-5"
      onClick={onSaveAddress}>
      Kaydet
    </button>
  </ModalFooter>
</Modal>)};
export default AddressModal;
解决方案

下面提供几种可行的实现方式:

1. 将表单状态提升到 AddressModal 组件

把AddressForm的状态托管到AddressModal中,通过props传递给表单组件:

修改 AddressModal.jsx

const AddressModal = ({ address, elementRef, hide, modalType }) => {
  // 初始化表单状态,编辑时用传入的address填充
  const [formState, setFormState] = useState(address || {
    name: '',
    phone: '',
    street: '',
    city: ''
  });

  const handleFormChange = (field, value) => {
    setFormState(prev => ({ ...prev, [field]: value }));
  };

  const onSaveAddress = () => {
    console.log('表单状态:', formState);
    // 这里可以调用保存接口等逻辑
    hide();
  };

  return (
    <Modal elementRef={elementRef} centered size="lg" fullscreen>
      <ModalBody>
        <AddressForm 
          address={address} 
          formState={formState} 
          onFormChange={handleFormChange} 
        />
      </ModalBody>
      <ModalFooter>
        <button
          type="button"
          className="btn btn-primary flex-grow-1 px-5"
          onClick={onSaveAddress}>
          Kaydet
        </button>
      </ModalFooter>
    </Modal>
  );
};
export default AddressModal;

修改 AddressForm.jsx(使其成为受控组件)

const AddressForm = ({ address, formState, onFormChange }) => {
  return (
    <div>
      <input
        type="text"
        value={formState.name}
        onChange={(e) => onFormChange('name', e.target.value)}
        placeholder="Name"
      />
      {/* 其他表单字段同理,都通过formState和onFormChange控制 */}
    </div>
  );
};
export default AddressForm;

2. 使用 useRef 引用 AddressForm 组件

如果AddressForm内部暴露了获取状态的方法,可以通过ref直接调用:

修改 AddressModal.jsx

import { useRef } from 'react';

const AddressModal = ({ address, elementRef, hide, modalType }) => {
  const formRef = useRef(null);

  const onSaveAddress = () => {
    // 调用AddressForm暴露的getFormState方法获取状态
    const formState = formRef.current?.getFormState();
    console.log('表单状态:', formState);
    hide();
  };

  return (
    <Modal elementRef={elementRef} centered size="lg" fullscreen>
      <ModalBody>
        <AddressForm ref={formRef} address={address} />
      </ModalBody>
      <ModalFooter>
        <button
          type="button"
          className="btn btn-primary flex-grow-1 px-5"
          onClick={onSaveAddress}>
          Kaydet
        </button>
      </ModalFooter>
    </Modal>
  );
};
export default AddressModal;

修改 AddressForm.jsx(使用 forwardRef 暴露方法)

import { forwardRef, useState, useImperativeHandle } from 'react';

const AddressForm = forwardRef(({ address }, ref) => {
  const [formState, setFormState] = useState(address || {
    name: '',
    phone: '',
    street: '',
    city: ''
  });

  // 暴露给父组件的方法
  useImperativeHandle(ref, () => ({
    getFormState: () => formState
  }));

  const handleChange = (field, value) => {
    setFormState(prev => ({ ...prev, [field]: value }));
  };

  return (
    <div>
      <input
        type="text"
        value={formState.name}
        onChange={(e) => handleChange('name', e.target.value)}
        placeholder="Name"
      />
      {/* 其他字段 */}
    </div>
  );
});

export default AddressForm;

3. 将状态提升到最上层的 Addresses 组件

如果后续需要在更多组件中使用表单状态,可以把状态放到Addresses中,通过props传递给AddressModal和AddressForm:

修改 Addresses.jsx

const Addresses = () => {
const [selectedAddress, setSelectedAddress] = useState();
const [modalType, setModalType] = useState();
const [formState, setFormState] = useState({});
const {
  elementRef: addressModalRef,
  show: showAddressModal,
  hide: hideAddressModal,
} = useModal();

const handleFormChange = (field, value) => {
  setFormState(prev => ({ ...prev, [field]: value }));
};

const onSaveAddress = () => {
  console.log('表单状态:', formState);
  // 保存逻辑
  hideAddressModal();
};

return (
  <>
    <div className="bg-light px-3 px-lg-4 py-4">
    <h1 className="h4 mb-4">My Addresses</h1>
    <div className="row g-3">
      <div className="col-12 col-md-6 col-lg-4">
        <AddressButton
          onClick={() => {
            setSelectedAddress(undefined);
            setModalType("NewAddress");
            // 重置表单状态
            setFormState({ name: '', phone: '', street: '', city: '' });
            showAddressModal();
          }}
        />
      </div>
      {ADDRESSES.map((address, i) => (
        <div className="col-12 col-md-6 col-lg-4" key={i}>
          <AddressButton
            {...address}
            onClick={() => {
              setSelectedAddress(address);
              setModalType("EditAddress");
              // 填充表单状态
              setFormState(address);
              showAddressModal();
            }}
          />
        </div>
      ))}
    </div>
  </div>

  <AddressModal
    address={selectedAddress}
    elementRef={addressModalRef}
    hide={hideAddressModal}
    modalType={modalType}
    formState={formState}
    onFormChange={handleFormChange}
    onSaveAddress={onSaveAddress}
  />
</>)};
export default Addresses;

修改 AddressModal.jsx

const AddressModal = ({ address, elementRef, hide, modalType, formState, onFormChange, onSaveAddress }) => {
  return (
    <Modal elementRef={elementRef} centered size="lg" fullscreen>
      <ModalBody>
        <AddressForm 
          address={address} 
          formState={formState} 
          onFormChange={onFormChange} 
        />
      </ModalBody>
      <ModalFooter>
        <button
          type="button"
          className="btn btn-primary flex-grow-1 px-5"
          onClick={onSaveAddress}>
          Kaydet
        </button>
      </ModalFooter>
    </Modal>
  );
};
export default AddressModal;

修改 AddressForm.jsx(同受控组件版本)

和第一种方案中的AddressForm一致,作为受控组件接收状态和回调。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:12:44