私の愛しいアップルパイへ
JavascriptライブラリーのReact.js便利ですよね。DatabaseとAjaxをガリガリ使って画面を更新していくようなWebサービスを作るときに重宝しています。今かなりハマっています。
フレームワークといえば規約やルールがあるので実装に悩むことが珍しくありませんが、React.jsでありがちなのが特定のDOMと連動してwindowやdocument、jQueryの独自イベントを使いたいときではないでしょうか。
例えば、jQuery UIを使いたいときや、特定の要素以外の場所をクリックしたときにポップアップを閉じたいとき、Windowがリサイズされたときに特定の処理を走らせたいときなどです。
今日はそのような処理をReact.jsではどう書くか解説していきます。
React.jsでwindowやdocumentやjQueryのイベントを使う方法
▼React.jsだと通常DOMの出力はこのように各Componentのrenderメソッドに記述していきます。
// レンダリング処理 render: function() { return ( <div className='reactRenderDiv'> <button onClick={this._popupOpen}>送信</button> </div> ); },
ただし、このタイミングではDOMが生成される前なので、ここに書いたDOMに対して後から独自イベントを実行したいときなどは適しません。
▼そこで登場するのが、DOM生成直後をフックできるcomponentDidMountメソッドです。
// 初回のレンダリング直後に呼び出されるメソッド componentDidMount: function() { // ここに処理を記述 }, // レンダリング処理 render: function() { return ( <div className='reactRenderDiv'> <button onClick={this._popupOpen}>送信</button> </div> ); },
このメソッドを使えば、DOMがレンダリングされた直後に処理を追記できます。ですから、ここで特定の要素に対する処理が書けるのです。
▼例えば、このDOMに連動して発火するdocumentへのイベント登録などはここに書いておくといいでしょう。これはポップアップを閉じるイベント登録の例です。
// 初回のレンダリング直後にdocumentにポップアップクローズ処理をセット componentDidMount: function() { document.addEventListener('click', this._popupClose); }, // レンダリング処理をここに書く render: function() { return ( <div className='reactRenderDiv'> <button onClick={this._popupOpen}>送信</button> </div> ); }, // 指定要素以外がクリックされたらポップアップを閉じる _popupClose: function(e) { if( !$(e.target).closest('.reactRenderDiv').length ){ this.setState({popup: false}); } },
▼もしくは、resizes処理などもここに書いておくと良いでしょう。
// 初回のレンダリング直後にdocumentにポップアップクローズ処理をセット componentDidMount: function() { document.addEventListener('click', this._popupClose); window.addEventListener('resize', this._windowResize); }, // レンダリング処理をここに書く render: function() { return ( <div className='reactRenderDiv'> <button onClick={this._popupOpen}>送信</button> </div> ); }, // 指定要素以外がクリックされたらポップアップを閉じる _popupClose: function(e) { if( !$(e.target).closest('.reactRenderDiv').length ){ this.setState({popup: false}); } },
▼jQuery UIのdatepickerを使うときなどもここに書きます。
// 初回のレンダリング直後にdocumentにポップアップクローズ処理をセット componentDidMount: function() { document.addEventListener('click', this._popupClose); window.addEventListener('resize', this._windowResize); $(".datepicker").datepicker(); }, // レンダリング処理をここに書く render: function() { return ( <div className='reactRenderDiv'> <input type="text" className="datepicker" /> <button onClick={this._popupOpen}>送信</button> </div> ); }, // 指定要素以外がクリックされたらポップアップを閉じる _popupClose: function(e) { if( !$(e.target).closest('.reactRenderDiv').length ){ this.setState({popup: false}); } },
▼また、DOMがアンマウントされたときには登録したイベントを解除しておくと良いでしょう。componentWillUnmountを使えば、このComponentがアンマウントされた直後の処理を追記できます。
// 初回のレンダリング直後にdocumentにポップアップクローズ処理をセット componentDidMount: function() { document.addEventListener('click', this._popupClose); window.addEventListener('resize', this._windowResize); $(".datepicker").datepicker(); }, // Componentがアンマウントされるときに登録したイベントも消す componentWillUnmount: function() { document.removeEventListener('click', this._popupClose); window.removeEventListener('resize', this._windowResize); }, // レンダリング処理をここに書く render: function() { return ( <div className='reactRenderDiv'> <input type="text" className="datepicker" /> <button onClick={this._popupOpen}>送信</button> </div> ); }, // 指定要素以外がクリックされたらポップアップを閉じる _popupClose: function(e) { if( !$(e.target).closest('.reactRenderDiv').length ){ this.setState({popup: false}); } },
これでReact.jsでもwindowやdocumentやjQueryのイベントを使うことができるようになります。
貴下の従順なる下僕 松崎より