【问题标题】:React Lifting State in Component with Containment用遏制反应组件中的提升状态
【发布时间】:2019-12-31 19:57:09
【问题描述】:

我目前有一个包含容器的模态系统。有一个 ModalWrapper 处理关闭模式和表单提交。实际的模态内容放在另一个组件中,我称之为 EventsModalForm:

模态包装器:

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { EVENT_FORM_MODAL } from '../layout/modalTypes';

const ModalWrapper = props => {
  const handleBackgroundClick = e => {
    if (e.target === e.currentTarget) props.hideModal();
  };

  const onOk = () => {
    if (props.modal.currentModal === EVENT_FORM_MODAL){
      //Do form submition 
    } else {
      props.onOk();
    }
    props.hideModal();
  };

  const [formStates, setFormStates] = useState({
    ...props.modal.form_fields
  });
  const handleFormChange = e => {
    return setFormStates({ ...formStates, [e.target.name]: [e.target.value] })    
  }


  const okButton = props.showOk
    ? (
      <button
        className="btn btn-primary"
        onClick={onOk}
        disabled={props.okDisabled}
      >
        {props.modal.okText}
      </button>
    ) : null;


  return (
    <div className="modal-overlay-div" onClick={handleBackgroundClick}>
      <div style={modal_content_div}>
        <header>
            <span>
              <button onClick={props.hideModal} className="close">&times;</button>
            </span>
            <h1>{props.title}</h1>  
          <hr />   
        </header>

        {props.children}

        {okButton}
      </div>
    </div>
  );
};
//content shortened for clarity  

export default ModalWrapper;

EventsModalForm:

import React from 'react';
import {
  Button,
  Form,
  FormGroup,
  Input,
  Label
} from "reactstrap";

import 'flatpickr/dist/themes/material_blue.css';
import Flatpickr from 'react-flatpickr';


import ModalWrapper from './ModalWrapper';

const EventsFormModal = props => {
  //have form hook here
  return (
    <ModalWrapper
      {...props}
      title="Event form"
      width={600}
      showOk={true}
    >
      <Form>
        //form...
      </Form>
    </ModalWrapper>
  );
};

export default EventsFormModal;

我正在尝试在 EventsFormModal 中使用钩子,并且每当调用 onOk 时,都会将状态传递给 ModalWrapper。但是,通过我的模态设置方式,我似乎无法找到将状态提升到 ModalWrapper 的方法。传递给 ModalWrapper 和 EventsFormModal 的道具是相同的,因此我无法在父组件中创建函数并将其作为道具传递给子组件。任何帮助,将不胜感激!

【问题讨论】:

  • onOk 被调用时,你只是想运行一个函数?我不清楚为什么你不能将回调作为道具传递,或者只是在EvensFormModal 中添加新状态。我不完全清楚你要做什么。
  • 我需要在表单中获取用户输入,并将其存储在挂钩中。必须将数据传递给父 ModalWrapper 才能调用函数并传递正确的参数。我必须仅将 onChange 函数传递给 EventsFormModal,但它也将以模态的方式传递给 ModalWrapper设置。
  • 我想我明白你的意思了。这可能不是最有帮助的,但对我来说,将表单作为一个处理自己的提交的组件会更有意义,它本身会触发模式中需要发生的任何操作(关闭等),这可以很容易作为道具传递下去,而不是试图提升状态,尽管这当然是可能的。
  • 那么您希望在有人在模态中单击“确定”后将 EventsFormModal 状态传递给 ModalWrapper?
  • 是的,这就是目标。

标签: javascript reactjs redux react-redux


【解决方案1】:

我假设您想在用户单击“确定”后将输入的数据传递回ModalWrapper。我制作了这个小演示来展示如何执行此类操作..

const { useState } = React;
const { render } = ReactDOM;

const SomeModal = () => {
  const [show, setShow] = useState(false);
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");

  const showModal = () => setShow(true);
  const hideModal = () => setShow(false);
  
  const handleNameChange = event => setName(event.target.value);
  const handleEmailChange = event => setEmail(event.target.value);

  return (
    <main>
      <ModalWrapper show={show} handleClose={hideModal} onOk={({name, email})}>
        <input type="text" onChange={handleNameChange} placeholder="Name" />
        <input type="text" onChange={handleEmailChange} placeholder="Email" />
      </ModalWrapper>
      <button type="button" onClick={showModal}>
        Open Modal
      </button>
    </main>
  );
};

const ModalWrapper = ({ handleClose, show, children, onOk }) => {
  const [onOkData, setOnOkData] = useState();
  const showHideClassName = show ? "modal display-block" : "modal display-none";
  
  const handleModalClose = (event, data) => {
    handleClose();
    setOnOkData(onOk);
  }

  return (
    <div>
    <div className={showHideClassName}>
      <section className="modal-main">
        {children}
        <button onClick={handleModalClose}>Ok</button>
      </section>
    </div>
      {onOkData 
        ? <pre>This data was sent from "SomeModal": {JSON.stringify(onOkData, null, 2)}</pre> 
        : ""}
    </div>
  );
};

const App = () => <SomeModal />

render(<App />, document.body);
.modal {
  position: fixed;
  top: 0;
  left: 0;
  width:100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.6);
}

.modal-main {
  position:fixed;
  background: white;
  width: 80%;
  height: auto;
  top:50%;
  left:50%;
  padding: 20px;
  transform: translate(-50%,-50%);
}

.display-block {
  display: block;
}

.display-none {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-01
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    相关资源
    最近更新 更多