【问题标题】:How can I set up a react modal to open from anywhere in the app?如何设置反应模式以从应用程序的任何位置打开?
【发布时间】:2017-05-07 05:46:21
【问题描述】:

我对 React 比较陌生,但我正在尝试设置一个可以从任何地方打开的模式。以下是我尝试打开模式的方式:

class SearchResults extends React.Component {
  static propTypes = {
    status: React.PropTypes.string.isRequired,
    results: React.PropTypes.array.isRequired,
    onResultClick: React.PropTypes.func.isRequired
  }

  constructor(props) {
    super(props)
  }

  onUploadButtonClick() {
    console.log('here');
  }

  render () {
    const uploadButtonFn = this.onUploadButtonClick
    let childElements = [];

    childElements.unshift((
      <div className="upload-button-wrapper" key="upload-button">
        <button type="button" className="upload-button" onClick={uploadButtonFn}><span>+</span> Upload Your Vidy</button>
      </div>
    ))

    return (
      <div className='search-results'>
        <div className='inner-content'>
          {(() => {
            if (this.props.status === 'fetching') {
              return <h1>searching</h1>
            }

            if (this.props.status === 'ready') {
              return (
                <Masonry
                    className={'my-gallery-class'} // default ''
                    elementType={'div'} // default 'div'
                    disableImagesLoaded={false} // default false
                    updateOnEachImageLoad={false} // default false and works only if disableImagesLoaded is false
                >
                  {childElements}
                </Masonry>
              )
            }
          })()}
        </div>
        <GetMoreResult />
      </div>
    )
  }
}

export default SearchResults

这就是我尝试打开模式的方式。我几乎肯定有更好的方法。我想我正在使用redux。我已经继承了这个项目,所以我可能不太好。

任何帮助将不胜感激。我想我需要在我的主布局中包含模式,但是我该如何触发它呢?

【问题讨论】:

    标签: reactjs redux react-modal


    【解决方案1】:

    不确定您的代码是如何工作的,connect() 在哪里?这里的任何地方都是我认为你想要使用 redux 的地方。这只是一个示例,因此您可以看到我们如何从任何其他组件显示模式,即使它不相关:

    //action
    const toggleModal = (isVisible) => ({
        type: "TOGGLE_MODAL",
        isVisible: isVisible
    });
    
    //reducer
    export default (state={}, action) => {
        switch (action.type) {
            case "TOGGLE_MODAL":
                return {...state, isVisible: action.isVisible}
            default:
                return state;
        }
    }
    
    //connect() allows us to dispatch an action
    class RandomClassElseWhereInApp extends connect()(React.Component {
        constructor(props) {
            super(props)
        }
        OpenModal = () => this.props.dispatch(toggleModal(true))
        render () {
            return (
            );
        }
    })
    
    //Gives us access to the store
    const mapStateToProps = (state) => ({
        state.Modal.isVisible
    });
    
    //This is a smart component
    class Modal extends connect(mapStateToProps)(React.Component {
      constructor(props) {
        super(props)
      }
      componentWillReceiveProps(nextProps) {
        //Empty string for display sets it to original value
        const display = "" ? this.props.isVisible : "none";
    
        this.setState({myModalStyle: {display: display}});
      }
      render () {
        return (
            <Popup style={this.state.myModalStyle}/>
        );
      }
    })
    
    //This is a dumb component
    const Popup = ({style}) => (
        <div class="popup" style={style} />
    );
    

    【讨论】:

      【解决方案2】:

      我们对此的解决方案是这样的:如果您使用的是 redux 和 react-redux。

      首先,创建一些动作创建者和一些 redux 状态来控制显示哪个模式。

      // modal-action-reducer.js
      
      export const ActionTypes = {
        CLOSE_MODAL: 'CLOSE_MODAL',
        OPEN_MODAL: 'OPEN_MODAL'
      };
      
      export const ActionCreators = {
        OpenModal = id => ({ type: ActionTypes.OPEN_MODAL, payload: { id } }),
        CloseModal: () => ({ type: ActionTypes.CLOSE_MODAL })
      };
      
      // this part of the state will be on something like `state.visibleModal`
      export const reducer = (state = null, action) => {
        switch (action.type) {
          case ActionTypes.OPEN_MODAL:
            return action.payload.id;
      
          case ActionTypes.CLOSE_MODAL:
            return null;
      
          default:
            return state;
        }
      };
      

      然后制作一个高阶组件来装饰您的实际模态 UI。

      // ModalDecorator.jsx
      
      import React from 'react';
      import {connect} from 'react-redux';
      import {ActionCreators} from './modal-action-reducer.js';
      
      export default function ModalDecorator (modalId) {
        return function (WrappedModalComponent) {
      
          class WrapperComponent extends React.Component {
            render () {
              const {isVisible, ...otherProps} = this.props;
              return isVisible
                ? <WrappedModalComponent {...otherProps} />
                : <div style={{ display: 'none' }} >;
      
            } 
          }
      
          // get whether this modal is visible by checking the state from the reducer against the modal id
          const mapStateToProps = state => ({
            isVisible: state.visibleModal === modalId
          });
      
          // for convenience we can add a closeModal prop to all modals
          const mapDispatchToProps = dispatch => ({
            closeModal: () => dispatch(ActionCreators.CloseModal());
          });
      
          return connect(mapStateToProps, mapDispatchToProps)(WrapperComponent);
        }
      }
      

      然后在你的实际模式中:

      // MyModal.jsx
      
      import React from 'react';
      import ModalDecorator from './ModalDecorator.jsx';
      
      class MyModal extends React.Component {
        render () { /* Do your thing here */ }
      }
      
      export default ModalDecorator('my-modal-id')(MyModal);
      

      这里需要注意的是,所有模态框都必须在某处呈现,因此为它们制作一个基本容器:

      // ModalDeclarations.jsx
      import MyModal from './MyModal.jsx';
      import SomeOtherModal from './SomeOtherModaal.jsx';
      
      const ModalDeclarations = () => (
        <div>
          <MyModal/>
          <SomeOtherModal/>
        </div>
      );
      
      export default ModalDeclarations;
      

      在 App.jsx 中

      import React from 'react'
      import ModalDeclarations from './ModalDeclarations.jsx';
      
      export default class App extends React.Component {
        render () {
          return (
            <div>
              {/* Other bits of your app here */}
              <ModalDeclarations />
            </div>
          );
        }
      }
      

      最后,我们可以在任何地方使用 OpenModal 动作创建器来打开任何模态。这是一个按钮,它将使用它的道具中的 modalId 打开模式。

      // ModalButton.jsx
      
      import React from 'react';
      import {connect} from 'react-redux';
      import {ActionCreators} from './modal-action-reducer.js';
      
      const mapDispatchToProps = (dispatch, ownProps) => ({
        openModal: () => dispatch(ActionCreators.OpenModal(ownProps.modalId))
      });
      
      class ModalButton extends React.Component {
        render () {
          return (
            <div onClick={this.props.openModal} >
              {this.props.children}
            </div>
          )
        }
      }
      
      export default connect(null, mapDispatchToProps)(ModalButton);
      
      ModalButton.propTypes = {
        modalId: React.PropTypes.string.isRequired
      };
      

      【讨论】:

        猜你喜欢
        • 2015-09-21
        • 1970-01-01
        • 2016-07-02
        • 1970-01-01
        • 2010-09-27
        • 2018-10-10
        • 2013-01-13
        相关资源
        最近更新 更多