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

时间:2021-06-26 07:01:35

标签: reactjs react-props react-component react-state

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

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

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

2 个答案:

答案 0 :(得分:1)

为了不复制状态,我会将模态中的输入包含在 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>
    );
  }
};

Edit react-passing-local-state-to-parent-component

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

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

模态组件示例:

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>
  );
}

Edit react-passing-local-state-to-parent-component (forked)

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

答案 1 :(得分:0)

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

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

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

并在渲染 Modal 组件时通过 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();
};

Edit react-passing-local-state-to-parent-component