Search code examples
reactjsreduxreact-modal

How can I set up a react modal to open from anywhere in the app?


I'm relatively new to React, but I'm trying to set up a modal that will open from anywhere. Here's how I'm trying to open a modal:

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

That's how Im trying to open a modal. I'm almost positive there are far better ways. I'm using redux, I think. I've inherited the project so I may not have it all right.

Any help would be greatly appreciated. I think I need to include the modal in my main layout, but then how do I trigger it?


Solution

  • Not sure how your code works really, where is the connect()? Anywhere here's what I think you want using redux. This is just an example so you can see how we can show a modal from any other component even if it's not related:

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