How to create a React Modal(which is append to `<body>`) with transitions?

后端 未结 8 1019
遥遥无期
遥遥无期 2020-12-07 08:23

There is a modal in this answer https://stackoverflow.com/a/26789089/883571 which is creating a React-based Modal by appending it to . However, I fo

相关标签:
8条回答
  • 2020-12-07 08:51

    The fundamental problem here is that in React you're only allowed to mount component to its parent, which is not always the desired behavior. But how to address this issue?

    I've made the solution, addressed to fix this issue. More detailed problem definition, src and examples can be found here: https://github.com/fckt/react-layer-stack#rationale

    Rationale

    react/react-dom comes comes with 2 basic assumptions/ideas:

    • every UI is hierarchical naturally. This why we have the idea of components which wrap each other
    • react-dom mounts (physically) child component to its parent DOM node by default

    The problem is that sometimes the second property isn't what you want in your case. Sometimes you want to mount your component into different physical DOM node and hold logical connection between parent and child at the same time.

    Canonical example is Tooltip-like component: at some point of development process you could find that you need to add some description for your UI element: it'll render in fixed layer and should know its coordinates (which are that UI element coord or mouse coords) and at the same time it needs information whether it needs to be shown right now or not, its content and some context from parent components. This example shows that sometimes logical hierarchy isn't match with the physical DOM hierarchy.

    Take a look at https://github.com/fckt/react-layer-stack/blob/master/README.md#real-world-usage-example to see the concrete example which is answer to your question:

    import { Layer, LayerContext } from 'react-layer-stack'
    // ... for each `object` in array of `objects`
      const modalId = 'DeleteObjectConfirmation' + objects[rowIndex].id
      return (
        <Cell {...props}>
            // the layer definition. The content will show up in the LayerStackMountPoint when `show(modalId)` be fired in LayerContext
            <Layer use={[objects[rowIndex], rowIndex]} id={modalId}> {({
                hideMe, // alias for `hide(modalId)`
                index } // useful to know to set zIndex, for example
                , e) => // access to the arguments (click event data in this example)
              <Modal onClick={ hideMe } zIndex={(index + 1) * 1000}>
                <ConfirmationDialog
                  title={ 'Delete' }
                  message={ "You're about to delete to " + '"' + objects[rowIndex].name + '"' }
                  confirmButton={ <Button type="primary">DELETE</Button> }
                  onConfirm={ this.handleDeleteObject.bind(this, objects[rowIndex].name, hideMe) } // hide after confirmation
                  close={ hideMe } />
              </Modal> }
            </Layer>
    
            // this is the toggle for Layer with `id === modalId` can be defined everywhere in the components tree
            <LayerContext id={ modalId }> {({showMe}) => // showMe is alias for `show(modalId)`
              <div style={styles.iconOverlay} onClick={ (e) => showMe(e) }> // additional arguments can be passed (like event)
                <Icon type="trash" />
              </div> }
            </LayerContext>
        </Cell>)
    // ...
    
    0 讨论(0)
  • 2020-12-07 08:52

    I think this code is more or less self explanatory and covers the core solution of what most people are looking for:

    ReactDOM.render(
      <Modal />,
      document.body.appendChild( document.createElement( 'div' ) ),
    )
    
    0 讨论(0)
提交回复
热议问题