MyFirstRails

React.jsの導入

概要

Railsにこれから初めて触れる方を対象にしたチュートリアルです

RailsとReact.jsを使ってサンプルアプリを作成します

チュートリアル

Railsのひな型を作る

まず、rails newを実行し、Railsアプリのひな型を作成します。

rails new reactjs --webpack=react

--webpackはRailsでWeboackを使いやすくしたWebpackerというものを使用するというオプションです

Vue、React、Angular、Elm、Stimulusを使用することができます

今回はReact.jsを使用するので--webpack=reactとしています

次に、作成したRailsアプリのディレクトリへと移動します。

cd reactjs

Foremanを使う

Webpackerを使う場合、ruby ./bin/webpack-dev-serverというコマンドを実行しつつ、rails sでローカルサーバーを起動する必要があります

その為、現状のままではターミナルを複数開いておく必要があり、少々面倒です

そこで、複数のコマンドを並列して実行できるforemanを使用します

まず、Gemfilegem 'foreman'を追記します

gem 'foreman'

その後、bundle install

bundle install

この時、sqlite3がインストールできないエラーが発生するかもしれません その場合は以下のようにsqlite3のバージョンを修正してbundle installを実行してください

gem 'sqlite3', '1.3.13'
bundle install

次に、foremanで使用するProcfile.devを作成します

web: bundle exec rails s
webpacker: ruby ./bin/webpack-dev-server

あとは、foreman start -f Procfile.devをターミナルで実行するだけです

foreman start -f Procfile.dev

localhost:5000にアクセスできればOkです(foremanを使用する場合、使用するポートが5000へと変更されています)

静的なファイルを作成

rails g controller コマンドを使い、コントローラーを作成します

rails g controller web index

その後、config/routes.rbを以下のように編集します

Rails.application.routes.draw do
  root 'web#index'
end

foreman start -f Procfile.devを実行して、localhost:5000でページが表示されていればOKです

React.jsを使う

まず、app/views/web/index.html.erbを以下のように変更します

<%= javascript_pack_tag 'hello_react' %>

最初に実行したrails newの段階でapp/javascript/packs/hello_react.jsが作成されています

それを<%= javascript_pack_tag 'hello_react' %>を使い、読み込んでいます

app/views/web/index.html.erbを編集後、foreman start -f Procfile.devを実行して、Hello Reactと表示されていればOKです!

React.js経由でBootstrapを使う

次に、React.js経由でBootstrapを使用してみたいと思います

まずはyarn add react-bootstrap bootstrapを実行し、React.js用のBootstrapを導入します

yarn add react-bootstrap bootstrap

次に、各コンポーネントを作成していきます

Headerコンポーネントとして利用するapp/javascript/packs/components/layouts/Header.jsxを作成します

import React from 'react'
import { Navbar, Nav, NavDropdown, Form, FormControl, Button,  } from 'react-bootstrap'

const Header = () => (
    <Navbar bg="light" expand="lg">
        <Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
        <Navbar.Toggle aria-controls="basic-navbar-nav" />
        <Navbar.Collapse id="basic-navbar-nav">
            <Nav className="mr-auto">
                <Nav.Link href="#home">Home</Nav.Link>
                <Nav.Link href="#link">Link</Nav.Link>
                <NavDropdown title="Dropdown" id="basic-nav-dropdown">
                    <NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
                    <NavDropdown.Item href="#action/3.2">Another action</NavDropdown.Item>
                    <NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
                    <NavDropdown.Divider />
                    <NavDropdown.Item href="#action/3.4">Separated link</NavDropdown.Item>
                </NavDropdown>
            </Nav>
            <Form inline>
                <FormControl type="text" placeholder="Search" className="mr-sm-2" />
                <Button variant="outline-success">Search</Button>
            </Form>
        </Navbar.Collapse>
    </Navbar>
)

export default Header;

react-bootstrapは以下のように各コンポーネントを呼び出して使います

import { Navbar, Nav, NavDropdown, Form, FormControl, Button,  } from 'react-bootstrap'

次に、Mainコンポーネントとして利用するapp/javascript/packs/components/layouts/Header.jsxを作成します

import React from 'react'

const Main = () => (
    <div className="container">
        <h1>Hello World! with React.js & Rails!</h1>
    </div>
)

export default Main;

Footerコンポーネントとして利用するapp/javascript/packs/components/layouts/Footer.jsx作成します

import React from 'react'

const Footer = (props) => {
    const {year} = props
    return (
        <div>
            Created Time {year}
        </div>
    )
}

export default Footer;

あとは、app/javascript/packs/index.jsを以下のように作成します

import React from 'react';
import ReactDOM from 'react-dom';

import Header from './components/layouts/Header'
import Main from './components/web/Main'
import Footer from './components/layouts/Footer'

class App extends React.Component {
    state = {
        year: 2019
    }
    render() {
        return (
            <div>
                <Header />
                <Main />
                <Footer year={this.state.year} />
            </div>
        );
    }
}

document.addEventListener("DOMContentLoaded", e => {
    ReactDOM.render(<App />, document.body.appendChild(document.createElement('div')))
})

最後に、app/views/web/index.html.erbを以下のように編集します

<link
  rel="stylesheet"
  href="https://maxcdn.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"
  integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
  crossorigin="anonymous"
></link>

<%= javascript_pack_tag 'index' %>

react-bootstrapではCSSが含まれていません

そのため、以下のようにCDN経由でCSSを導入する必要があります

<link
  rel="stylesheet"
  href="https://maxcdn.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"
  integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
  crossorigin="anonymous"
></link>

あとは、foreman start -f Procfile.devをターミナルで実行します

localhost:3000にアクセスしてBootstrapが適用されていればOKです!