React.jsのポータル

画像







おそらく、各フロントエンド開発者は、さまざまな種類のドロップダウンまたはツールチップを実行する必要がありました。 そしてほとんどの場合、 overflow: hidden



そのようなものを要素内に表示する必要があります。 SmartProgressにはそのような瞬間が訪れました。







SmartProgressでは、Reactを使用してインターフェイスを開発しており、実際に反応型ソリューションを探していました。 ポータルは私たちを助けるために急いでいます。









ポータルは、コンテンツをDOMの別の部分、たとえば<body>



最後にレンダリングするコンポーネントです。 この動作により、たとえばoverflow: hidden



を使用してブロック外の要素を表示できますが、同時にコンポーネントツリーを最小限に変更できます。







通常、ポータルはモーダルウィンドウに使用されます(これも非常に便利です)が、アイデアを少し変更し、ニーズに合わせて調整します。 位置を指定したブロックのような動作が必要です:absoluteおよびmargin-top / margin-left。 このコンポーネントをRelativePortalと呼びます。







コンポーネントのインターフェースを定義してから、その実装を記述するのが便利です。

たとえば、次のコードがあります。







 <div className="calendarLink"> <a className="calendarLink__trigger"> </a> {isOpen && <CalendarDropdown />} </div>
      
      





ポータルを使用すると、コードは次のように変わります。







 <div className="calendarLink"> <a className="calendarLink__trigger"> </a> <RelativePortal left="0" top="0"> {isOpen && <CalendarDropdown />} </RelativePortal> </div>
      
      





今、あなたはビジネスに取りかかることができます。 jsfiddleの例を使用して各ステップを説明します。 問題が見える初期状態は次のとおりです-https://jsfiddle.net/Sunify/1k18wxm1/1/







ポータルの作成方法(注意-ES6!)



ポータルのrenderメソッドはnullを返すため、コンポーネントが呼び出される場所では何もレンダリングしません。 代わりに、コンポーネントライフサイクルメソッドの1つ、たとえばcomponentDidUpdateでReactDOM.renderを使用します。







 class RelativePortal extends React.Component { ... //  null         render() { return null; } //        componentDidUpdate() { ReactDOM.render( <div {...this.props}>{this.props.children}</div>, this.node ); } ... }
      
      





戦いの半分は完了しましたが、ドロップアウトはページの下部に表示されます( https://jsfiddle.net/Sunify/kr8hehca/)-修正する必要があります!







 class RelativePortal extends React.Component { ... //   ,  React.findDOMNode(this)   null render() { return <span />; } //         componentDidMount() { this.handleResize = () => { const rect = React.findDOMNode(this).getBoundingClientRect(); const left = window.scrollX + rect.left; const top = window.scrollY + rect.top; if(top !== this.state.top || left !== this.state.left) { this.setState({ left, top }); } }; window.addEventListener('resize', this.handleResize); this.handleResize(); } //              componentDidUpdate() { ReactDOM.render( <div {...this.props} style={{ position: 'absolute', top: this.state.top + this.props.top, left: this.state.left + this.props.left }} > {this.props.children} </div>, this.node ); } ... }
      
      





これで、必要な場所にドロップダウンが表示され、そのようなタスク用のユニバーサルコンポーネントが作成されました。

https://jsfiddle.net/Sunify/4fmdugrr/







このメソッドには明らかな利点があります。機能し、最小限のインターフェースであり、普遍的です-RelativePortalで何でもラップできます。







しかし、これには重大な欠点もあります-CSSカスケードを失います。 フォント、色などを継承しません。 機能しない:hover-ホバー状態はコンポーネント状態に保存する必要があります。 たとえば、これはhttps://jsfiddle.net/Sunify/nz7wyee3です。 私たちにとってこれは重要ではないので、このソリューションは私たちに合っています。







このようなコンポーネントを積極的に使用し、npmに配置しました。 それを使用してください








All Articles