React:将本地状态传递给父组件

React: Passing local state to parent component

我正在尝试在 React 中创建一个可重用的“模态”组件。 Modal 组件将有一些输入字段和一个提交按钮,当用户单击 Modal 中的提交按钮时。模式应该关闭,用户在输入字段中输入的数据应该通过在父组件中声明的回调函数传递给父组件。代码工作正常,但我认为(不确定)这不是正确的解决方案,因为我必须在 Modal(子)组件和使用 Modal 组件的父组件中创建“反应状态”。如您所见(沙盒代码),状态在两个组件中都是重复的,我想知道如何才能将状态保持在一个地方。我的理解是我肯定需要在 Modal 组件中为输入字段创建一个状态以跟踪更改,但我不确定如何在不创建相同状态的情况下在父组件中使用该数据

这是我创建的一个沙盒,用于展示我到目前为止所做的工作:

https://codesandbox.io/s/jovial-matsumoto-1zl9b?file=/src/Modal.js

您可以在 App 组件中定义这些状态:

const [showModal, setShowModal] = useState(false);
const [user, setUser] = useReducer(reducer, {
    firstName: "",
    lastName: ""
});

const toggleModal = () => {
    setShowModal(!showModal);
};

并在渲染模态组件时通过 props 传递它们:

<div className="App">
    <h2>First Name is : {firstName}</h2>
    <h2>Last Name is : {lastName}</h2>
    <button className="toggle-button" onClick={toggleModal}>
        Show Modal
    </button>
    <Modal
        show={showModal}
        hide={() => toggleModal(false)}
        user={user}
        updateUser={setUser}
    />
</div>

然后,在您的 Modal 组件中,为 firstNamelastName 定义状态:

const Modal = (props) => {
    const [firstName, setFirstName] = useState(props.user.firstName);
    const [lastName, setLastName] = useState(props.user.lastName);

    const onFirstNameChange = ({ target }) => {
        setFirstName(target.value);
    };

    const onLastNameChange = ({ target }) => {
        setLastName(target.value);
    };
    
    // ...
}

现在您可以从 Modal 组件提交这样的更改:

const onFormSubmit = (e) => {
    props.updateUser({
        firstName,
        lastName
    });
    props.hide();
};

为了不重复状态,我会将模态中的输入包含在 form 元素中,并将输入转换为不受控制的输入。提交表单后,获取表单字段值并传入 formData 回调并重置表单。显式声明按钮为 type="submit".

const Modal = (props) => {
  const onFormSubmit = (e) => {
    e.preventDefault();

    const firstName = e.target.firstName.value;
    const lastName = e.target.lastName.value;

    props.formData({ firstName, lastName });
    e.target.reset();
  };

  if (!props.show) {
    return null;
  } else {
    return (
      <div className="modal" id="modal">
        <form onSubmit={onFormSubmit}>
          <input type="text" name="firstName" />
          <input type="text" name="lastName" />
          <button className="toggle-button" type="submit">
            Submit
          </button>
        </form>
      </div>
    );
  }
};

看来你问题的症结在于你的父组件和模态之间的代码重复。我在这里真正建议的是将模式与任何特定用例分离,并允许任何消费父组件传递关闭处理程序和子组件。

这将状态保留在父级中,从而控制。

模态组件示例:

const Modal = ({ onClose, show, children }) =>
  show ? (
    <div className="modal" id="modal">
      <button type="button" onClick={onClose}>
        X
      </button>
      {children}
    </div>
  ) : null;

家长:

function App() {
  const [isShowModal, setIsShowModal] = useState(false);
  const [firstName, setFirstName] = useState();
  const [lastName, setLastName] = useState();

  const showModal = (e) => {
    setIsShowModal((show) => !show);
  };

  const closeModal = () => setIsShowModal(false);

  const onFormSubmit = (e) => {
    e.preventDefault();

    const firstName = e.target.firstName.value;
    const lastName = e.target.lastName.value;

    setFirstName(firstName);
    setLastName(lastName);

    e.target.reset();
    closeModal();
  };

  return (
    <div className="App">
      <h2>First Name is : {firstName}</h2>
      <h2>Last Name is : {lastName}</h2>
      <button className="toggle-button" onClick={showModal}>
        Show Modal
      </button>
      <Modal show={isShowModal} onClose={closeModal}>
        <form onSubmit={onFormSubmit}>
          <input type="text" name="firstName" />
          <input type="text" name="lastName" />
          <button className="toggle-button" type="submit">
            Submit
          </button>
        </form>
      </Modal>
    </div>
  );
}

这完全取决于您要如何管理父内容和模态内容之间的交互。我已经展示了使用表单和表单操作,因此在用户提交表单之前您的状态不会更新。您可以使用表单实用程序(redux-form、formix 等)或滚动您自己的管理。生活是一座花园,去挖掘吧。