【问题标题】:How to trigger react-modal from the layout container?如何从布局容器触发反应模式?
【发布时间】:2017-12-29 05:19:01
【问题描述】:

我正在我的 React+Redux+ReactRouter4 应用程序中使用 react-modal

我有一个 MainLayout 容器和一个 Home 容器。

模态只会在主容器被渲染时使用,所以我在主容器内有 ReactModal 的逻辑。我可以像这样轻松地从 Home Container 中打开模式:

<button onClick={this.openModal}>Open Modal</button>

问题是MainLayout容器有一个导航也需要打开modal的能力,但是很明显this.openModal那里不存在...如何让MainLayoutContainer在Home容器中打开modal ?

class Home extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      modalIsOpen: false
    };
    this.openModal = this.openModal.bind(this);
    this.closeModal = this.closeModal.bind(this);

  }

  openModal() {
    this.setState({modalIsOpen: true});
  }

  closeModal() {
    this.setState({modalIsOpen: false});
  }

  render() {
    return (
      <div>
        ....
        <button onClick={this.openModal}>Open Modal</button>

        <Modal
          isOpen={this.state.modalIsOpen}
          onAfterOpen={this.afterOpenModal}
          onRequestClose={this.closeModal}
          style={modalCustomStyles}
          contentLabel="Example Modal"
        >
          <h2 ref={subtitle => this.subtitle = subtitle}>Hi</h2>
          <button onClick={this.closeModal}>close</button>
          <div>I am a modal</div>
        </Modal>

      </div>
    )
  };

};

App.jsx

const WithMainLayout = ({component: Component, ...more}) => {
  return <Route {...more} render={props => {
    return (
      <MainLayout {...props}>
        <Component {...props} />
      </MainLayout>
    );
  }}/>;
};    
....
<WithMainLayout exact path="/" component={Home} />

【问题讨论】:

    标签: reactjs react-router react-redux react-router-redux react-modal


    【解决方案1】:

    我要做的只是将 modalOpenState 移动到 redux 中,而不是将其保持在本地状态。你的初始状态应该是这样的。

    export default {
      modalIsOpen: false
    };
    

    然后编写一个动作来切换商店中的模态状态。

    export function toggleQuestionModal(isOpen) {
      return { type: types.TOGGLE_QUESTION_MODAL, payload: isOpen };
    }
    

    你的模态展示组件应该是这样的。

    import React, { Component, PropTypes } from 'react';
    import Modal from 'react-modal';
    
    const QuestionModal = ({ modalIsOpen, openModal, closeModal, afterOpenModal }) => {
      const customStyles = {
        overlay: {
          position: 'fixed',
          top: 0,
          left: 0,
          right: 0,
          bottom: 0,
          backgroundColor: 'rgba(0, 0, 0, 0.75)'
        },
    
        content: {
          top: '50%',
          left: '50%',
          right: 'auto',
          bottom: 'auto',
          marginRight: '-50%',
          height: '50%',
          width: '80%',
          transform: 'translate(-50%, -50%)'
        }
      };
    
      return (
        <div>
          <button onClick={openModal}>Open Modal</button>
          <Modal
            isOpen={modalIsOpen}
            onAfterOpen={afterOpenModal}
            onRequestClose={closeModal}
            style={customStyles}
            contentLabel="Create A Question"
            role="dialog"
          >
    
            <h2>Hello</h2>
            <button onClick={closeModal}>close</button>
            <div>I am a modal</div>
            <form>
              <input />
              <button>tab navigation</button>
              <button>stays</button>
              <button>inside</button>
              <button>the modal</button>
            </form>
          </Modal>
        </div>
      );
    };
    
    QuestionModal.propTypes = {
      modalIsOpen: PropTypes.bool.isRequired,
      openModal: PropTypes.func.isRequired,
      closeModal: PropTypes.func.isRequired,
      afterOpenModal: PropTypes.func.isRequired
    };
    
    export default QuestionModal;
    

    最后,这是您的模态容器组件。

    import React, { Component, PropTypes } from 'react';
    import { connect } from 'react-redux';
    import { bindActionCreators } from 'redux';
    import { toggleQuestionModal, toggleConfirmation } from '../actions/questionActions';
    import QuestionModal from '../components/questionModal';
    
    class QuestionPage extends Component {
        constructor(props, context) {
            super(props, context);
            this.openModal = this.openModal.bind(this);
            this.closeModal = this.closeModal.bind(this);
            this.afterOpenModal = this.afterOpenModal.bind(this);
        }
    
    
        openModal() {
            this.props.toggleQuestionModal(true);
        }
    
        afterOpenModal() {
            // references are now sync'd and can be accessed. 
            // this.subtitle.style.color = '#f00';
        }
    
        closeModal() {
            this.props.toggleConfirmation(true);
        }
    
        render() {
            const { modalIsOpen } = this.props;
            return (
                <div>
                    <QuestionModal modalIsOpen={modalIsOpen} openModal={this.openModal} closeModal={this.closeModal} 
                    afterOpenModal={this.afterOpenModal} />
                </div>
            );
        }
    }
    
    QuestionPage.propTypes = {
        modalIsOpen: PropTypes.bool.isRequired,
        toggleQuestionModal: PropTypes.func.isRequired,
    };
    
    function mapStateToProps(state, ownProps) {
        return {
            modalIsOpen: state.question.modalIsOpen
        };
    }
    
    function mapDispatchToProps(dispatch) {
        return {
            toggleQuestionModal: bindActionCreators(toggleQuestionModal, dispatch),
        };
    }
    
    export default connect(mapStateToProps, mapDispatchToProps)(QuestionPage);
    

    当您想从任何组件打开模式时,只需调用具有真值的toggleQuestionModal 操作。这将改变状态并呈现模态。 Redux 建议将所有内容保持在 state 中。我确实这样做。不要把东西放在本地。保持一切状态使您更容易使用工具进行时间旅行调试。您可以找到示例实现here。希望这可以帮助。快乐编码!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-22
      • 2018-07-21
      相关资源
      最近更新 更多