react-railsでのモーダルの実装の方法をまとめます。
npmでReactのモーダル系ライブラリをインストールすればさくっと実装できるのですが、今回npmが使えないRails環境だったので、Gemを使った方法と自前実装する方法について見ていきます。
Gemを使って簡単に実装する場合
react_rails_modalを使います。
インストール
まずreact-railsとreact_rails_modalをGemfileに追加します。
gem 'react-rails'
gem 'react_rails_modal'
インストールします。
$ bundle install
インストールコマンドを実行します。
$ rails g react:install
$ rails g react_rails_modal:install
これによりapplication.js
に下記が追記されます。
//= require react
//= require react_ujs
//= require components
//= require react_rails_modal
これでマニフェストファイルにライブラリの読み込みが宣言されました。
初期設定
続いて、react-railsの環境変数を設定します。
# config/environments/development.rb
MyApp::Application.configure do
config.react.variant = :development
end
# config/environments/production.rb
MyApp::Application.configure do
config.react.variant = :production
end
使い方
jsxファイルの中でModalComponentコンポーネントを宣言して使います。
<ModalComponent
isOpen={bool}
onCloseRequest={requestCloseFunction}
style={customStyle}
>
<h1>Modal Component Content</h1>
<p>Text</p>
</ModalComponent>
実装例
具体的な使い方は下記のようになります。
app/controller/views/
以下のテンプレートファイルで、Reactコンポーネントを呼び出します。
今回はHelloコンポーネントを呼び出しています。
<%= react_component('Hello') %>
Helloコンポーネントはjsxファイルの中で定義します。
その中でModalComponentを呼び出しており、ここがモーダル部分になります。
モーダルの開閉状態をstateで持って、クリックに応じてモーダルの開閉状態を切り替える関数を用意しています。
スタイルに関してはオーバーレイとモーダル本体それぞれを指定することができます。
class Hello extends React.Component {
constructor(props) {
super(props);
this.closeModal = this.closeModal.bind(this);
this.openModal = this.openModal.bind(this);
this.state = { isModalOpen: false };
}
closeModal() {
this.setState({ isModalOpen: false });
}
openModal() {
this.setState({ isModalOpen: true });
}
render () {
return (
<div>
<button onClick={this.openModal}>Open Modal</button>
<ModalComponent
isOpen={this.state.isModalOpen}
onCloseRequest={this.closeModal}
style={Hello.styles}
>
<h1>Hello world!</h1>
<button onClick={this.closeModal}>Close</button>
</ModalComponent>
</div>
);
}
}
Hello.styles = {
overlay: {
backgroundColor: 'rgba(0,0,0,0.75)',
bottom: '0',
height: '100%',
position: 'fixed',
top: '0',
left: '0',
right: '0',
width: '100%',
zIndex: '1',
},
modal: {
background: '#fff',
left: '5%',
padding: '15px 30px',
position: 'relative',
top: '10%',
width: '80%',
zIndex: '2',
}
}
これでモーダル完成です。
自前実装する場合
ここからは自前実装する方法について見ていきます。
app/controller/views/
以下のテンプレートファイルで、Reactコンポーネントを呼び出します。
<%= react_component('Hoge') %>
Hogeコンポーネントの中でModalコンポーネントを呼び出します。
親であるHogeコンポーネントで、モーダルの開閉状態のstateおよびその関数は定義します。
class Hoge extends React.Component {
constructor(props) {
super(props);
this.closeModal = this.closeModal.bind(this);
this.openModal = this.openModal.bind(this);
this.state = { isModalOpen: false };
}
closeModal() {
this.setState({ isModalOpen: false });
}
openModal() {
this.setState({ isModalOpen: true });
}
render() {
return (
<div>
<button onClick={this.openModal}>Open Modal</button>
<Modal isOpen={this.state.isModalOpen} onClose={this.closeModal} />
</div>
);
}
}
Modalコンポーネントの中では、引数として渡されたthis.props.isOpen
がfalse
の場合、null
を返しています。
これによりモーダルを非表示にできます。
class Modal extends React.Component {
render() {
if (!this.props.isOpen) {
return null;
}
return (
<div>
<div onClick={this.props.onClose} style={Modal.styles.overlay} />
<div style={Modal.styles.content}>
<h1>Hello modal!</h1>
<button onClick={this.props.onClose}>Close</button>
</div>
</div>
);
}
}
Modal.styles = {
overlay: {
backgroundColor: 'rgba(0,0,0,0.75)',
bottom: '0',
height: '100%',
position: 'fixed',
top: '0',
left: '0',
right: '0',
width: '100%',
zIndex: '1',
},
content: {
background: '#fff',
left: '5%',
padding: '15px 30px',
position: 'relative',
top: '10%',
width: '80%',
zIndex: '2',
}
}
以上でモーダルを自前実装できました。
親クラスでモーダルの開閉状態を管理することと、モーダルが閉じているときはrenderでnull
を返すようにすればモーダルの実装が簡単になると思います。