JavaScript 初心者な Rubyist が React 学習環境を準備した話

## はじめに

JavaScript のフレームワークを何も知らない Rubyist がちょっと React を勉強しようと思いローカル環境で勉強したいと思い、少し環境を整理しました。

[Getting Started](https://reactjs.org/docs/getting-started.html) から始まるページでは、 [CodePen](https://codepen.io/) を使うようになっているのですが、自分の好きなエディタで編集できた方がやりやすいのですよね。

かといって、本格的に React を npm でインストールして、Project 作ってとか、大袈裟なこともしたくないです。
お手軽な学習のための環境を用意することにしたいと思います。

## index.html を用意する

まずは動作を試せるように雛形として使い回せる index.html を用意します。
index.js を読み込む時 `type='text/babel'` を指定することを忘れないようにしてください。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.1/umd/react.development.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.1/umd/react-dom.development.js"></script>
  <script type="text/babel" src="index.js"></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
  <title></title>
</head>
<body>
  <dev id="root"></dev>
</body>
</html>
```

## index.js を用意する

後は、 index.js を index.html と同じディレクトリに作って好きなように index.js を書いていけば良いだけなのですが、動作確認のため、
[Hello World](https://reactjs.org/docs/hello-world.html) をやってみましょう。

```javascript:index.js
ReactDOM.render(
  <h1>Hello, World</h1>,
  document.getElementById('root')
);
```

## HTTPサーバーを用意する

Chrome で index.html を開いても Reactは動作しません。
HTTPサーバーを動作させて、http でアクセスして表示してやる必要があります。
npm でなんかそれっぽい物をインストールすれば良いのかも知れませんが、良くわかりません。
そう、そんなRubyistには強い味方、Ruby (Webrick) があるのです。

Webrick を使って、 httpsrv.rb を作ります。
httpsrv.rb は PATH の通ったディレクトリに保存して、実行権限をつけておきます。

```ruby:httpsrv.rb
#!/usr/bin/env ruby
require 'webrick'

port = ARGV.shift || 28_080
srv = WEBrick::HTTPServer.new(Port: port, DocumentRoot: '.')
trap('INT') { srv.shutdown }
srv.start
```


## HTTPサーバーを実行する

httpsrv.rb を index.html を保存したディレクトリで実行します。

```shell
$ httpsrv.rb
[2018-08-20 12:48:50] INFO  WEBrick 1.4.2
[2018-08-20 12:48:50] INFO  ruby 2.6.0 (2018-08-10) [x86_64-darwin17]
[2018-08-20 12:48:50] INFO  WEBrick::HTTPServer#start: pid=63672 port=28080
```

## ブラウザで表示する

`http://localhost:28080/index.html` を Chrome で表示します。

babel の警告は表示されますが、Chromeで表示できました。（学習用なんだから警告出てもこれでおっけー。）
<img width="626" alt="react_ss.png" src="https://qiita-image-store.s3.amazonaws.com/0/209941/aac6eda4-9731-17e5-7b8a-ba1dcb6a48cb.png">


## import が使えない

import が使えないっぽいので、そういうのは以下みたいな感じで回避してください。

```
import { Fragment } from 'react'
```

は

```
const Fragment = React.Fragment;
```

な感じです。

## Redux も使いたいよ

index.html の script タグに追加します。

```html:index.html
  <script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.7/react-redux.min.js"></script>
```

import を使われているところ

```javascript
import { Provider } from 'react-redux'
```

などは、こんな感じで回避すれば良いと思います。

```javascript
const Provider = ReactRedux.Provider;
```

どこかのページにあったカウンターの例を写経したものです。

```react:index.js
const connect = ReactRedux.connect;
const Provider = ReactRedux.Provider;

class Counter extends React.Component {
  increment = () => {
    this.props.dispatch({type: 'INCREMENT'})
  }

  decrement = () => {
    this.props.dispatch({type: 'DECREMENT'})
  }

  render() {
    return (
      <div>
        <h2>Counter</h2>
        <div>
          <button onClick={this.decrement}>-</button>
          <span>{this.props.count}</span>
          <button onClick={this.increment}>+</button>
        </div>
      </div>
    )
  }
}

const mapStateToProps = (state) => ({
  count: state.count
});

const initialState = {
  count: 0
};

function reducer(state = initialState, action) {
  switch(action.type) {
    case 'INCREMENT':
      return {
        count: state.count + 1
      };
    case 'DECREMENT':
      return {
        count: state.count - 1
      };
    default:
      return state;
  }
}

Counter = connect(mapStateToProps)(Counter);

const store = Redux.createStore(reducer);

const App = () => (
    <Provider store={store}>
      <Counter />
    </Provider>
);

ReactDOM.render(<App />, document.getElementById('root'))
```

## おわりに

こんな環境で React を少しずつ、勉強しているところです。
うちの社名が社名なので、Reactだけど、ほんのちょっぴりRubyネタを(無理矢理？)絡めてみました。