React JS × Onsen UI 入門

# Onsen UIについて
公式ページ

https://ja.onsen.io/v2/guide/react/


### 以下公式サイトから抜粋
* モバイルアプリの開発に特化したUIコンポーネントの集まり
* ネイティブなiOSとAndroidのデザインガイドに準拠したデザインと機能を持ってる
* 無料で利用でき、完全にオープンソースなソフトウェア

### Onsen UIが吸収する各OSのUIの違い
例えば、AndroidではタブがUIでは上にあることがスタンダードとなっていて、iOSではタブがUIでは下にあることがスタンダードとなっています。
Onsen UIではこの2つの異なるUIを同じソースコードで実装できます。

他にも、新規のスクリーンがUIに重なる場合、iOSのデフォルトでは右からスライドしてきますが、Androidでは下からフェードしつつ重なってきます。このような細かいインタラクションの表現もOnsen UIでは自動で吸収してくれます。

UserAgentでCSSやJSの切り替えを行っているので、ChromeのデベロッパーツールでもUserAgentoを切りかるだけでUIの表現が変わるのを確認できます。

# React.js と Onsen UI
Onsen UIが2.0になって、React JSと組み合わせて使えるようになりました。
※Onsen UI1.0はAngular JS 1.*系のみサポート

```
$ npm install -g create-react-app
$ npx create-react-app my-app
$ cd my-app
$ yarn add onsenui react-onsenui --save-dev
$ yarn start
```



``` src/App.js 
import logo from './logo.svg';
import './App.css';


// ボタンコンポーネントのインポート
import { Button } from 'react-onsenui';
// Onsen UIのCSSのロード
import "onsenui/css/onsen-css-components.css"

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Button modifier="outline">
          button
        </Button>
      </header>
    </div>
  );
}

export default App;
```

以下のように、いつものReactのデフォルトページにOnsen UIのボタンが追加されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74622/0adcd590-c052-a44f-ebae-394f1929a559.png" width="200" />


# Onsen UIを利用したナビゲーション
Onsen UIを利用してページ遷移を実装します。
Navigationというコンポーネントを利用します。

``` src/App.js
import logo from './logo.svg';
import './App.css';

// ボタンコンポーネントのインポート
import { Button } from 'react-onsenui';
// Onsen UIのCSSのロード
import "onsenui/css/onsen-css-components.css"

import Block from './components/block'

function App() {
  return (
    <div key="App" className="App">
      <header className="App-header">
        <Block />
      </header>
    </div>
  );
}

export default App;
```

``` src/components/block.js
import React from 'react';
import {Navigator, Page, Button, Toolbar, BackButton} from 'react-onsenui';
import "onsenui/css/onsen-css-components.css"

class MainPage extends React.Component {
  pushPage() {
    this.props.navigator.pushPage({component: SecondPage});
  }

  render() {
    return (
      <Page key="page1">
        <Toolbar>
          <div className="center">Navigator</div>
        </Toolbar>

        <p style={{textAlign: 'center'}}>
          <Button onClick={this.pushPage.bind(this)}>Push page</Button>
        </p>
      </Page>
    );
  }
}

class SecondPage extends React.Component {
  pushPage() {
    this.props.navigator.pushPage({component: SecondPage});
  }

  popPage() {
    this.props.navigator.popPage();
  }

  render() {
    return (
      <Page key="page2">
        <Toolbar>
          <div key="div1" className="left"><BackButton>Back</BackButton></div>
          <div key="div2" className="center">Another page</div>
        </Toolbar>

        <p style={{textAlign: 'center'}}>
          <Button key="button2" onClick={this.popPage.bind(this)}>Pop page</Button>
        </p>
      </Page>
    );
  }
}

class Block extends React.Component {
  renderPage(route, navigator) {
    const props = route.props || {};
    props.navigator = navigator;
    props.key = route.component.name;

    return React.createElement(route.component, props);
  }

  render() {
    return (
      <Navigator
        key="nav1"
        initialRoute={{component: MainPage}}
        renderPage={this.renderPage}
      />
    );
  }
}

export default Block;
```

# 各OSでのUIの違い
以下のようにNavigationではOSでUIが異なります

**Androidでの見た目**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74622/2ec499e1-bf9b-22e6-3582-45e73ae6da33.png" width="200">

**iOSでの見た目**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74622/da352f27-4398-e6a6-fc9c-3fed4b3e5b61.png" width="200">