React Portals
了解如何使用 React Portals
React 16 於 2017 年 9 月发布了 Portals。
Portal 是在組件層次結構之外的地方渲染元素的方法,它位於一個獨立的組件中。
當該元素被渲染時,它上發生的事件將由 React 組件層次結構管理,而不是由 DOM 位置所定義的層次結構管理。
因此有了 “portal” 這個名字:一個元素存在於 DOM 樹的某個位置,超出了普通的 React 組件樹,但包含它的 React 組件樹仍然負責管理它。
React 提供了一個簡單的 API 來實現這一點,即 ReactDOM.createPortal() ,它接受兩個參數。第一個是要渲染的元素,第二個是要渲染到的 DOM 元素。
這一功能的典型用例是模態窗口。
模態窗口要全屏渲染,必須存在於元素之外,以便可以使用 CSS 正確地應用樣式。
所以如果把模態窗口定義為一個組件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   | class Modal extends React.Component {  constructor(props) {  super(props)  this.el = document.createElement('div')  }
   componentDidMount() {  document.getElementById('modal').appendChild(this.el)  }
   componentWillUnmount() {  document.getElementById('modal').removeChild(this.el)  }
   render() {  return ReactDOM.createPortal(  this.props.children,  this.el  )  } }
  | 
 
我們可以在 App 組件中渲染它,並且即使技術上模態窗口是在不同的 DOM 樹中渲染的,也會由 App 組件處理模態窗口中發生的所有事件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
   | class App extends React.Component {  constructor(props) {  super(props)  this.state = {showModal: false}
   this.handleShow = this.handleShow.bind(this)  this.handleHide = this.handleHide.bind(this)  }
   handleShow() {  this.setState({showModal: true})  }
   handleHide() {  this.setState({showModal: false})  }
   render() {  const modal = this.state.showModal ? (  <Modal>  <div>  The modal <button onClick={this.handleHide}>Hide</button>  </div>  </Modal>  ) : ''
   return (  <div>  The app <button onClick={this.handleShow}>Show modal</button>  {modal}  </div>  )  } }
  ReactDOM.render(<App />, document.getElementById('app'))
  | 
 
在 https://codepen.io/flaviocopes/pen/KbdagX 可以看到完整的示例。
tags: [“React”, “Portals”, “modal”, “DOM hierarchy”]