ReactNativeでアプリを作る時の個人的な構成(水平分割バージョン)

[ReactNativeでアプリを作る時の個人的な最小構成](http://qiita.com/razokulover/items/7b1b8245d9f56cadf472)はいわゆる垂直分割の構造だったが、大きめの規模になることがわかっている場合は最初から水平分割の構造で作るのもよいと思う。

[GitPoint](https://github.com/gitpoint/git-point)を参考にして考えてみた。

具体的にはこんな感じ。

```
index.ios.js
index.android.js
App.js
root.reducer.js
root.store.js
routes.js
src
|__components
|__api
|__config
|__utils
|__containers
  |__home
     |__home.action.js
     |__home.reducer.js
     |__home.type.js
     |__screens
       |__index.js
```

- ページ単位でディレクトリを切って、その中にredux関連のファイルとページ関係のファイルをまとめる。

- ヘッダーとかボタンとか共通のcomponentsはsrc/components配下に置く。

- styleは各コンポーネント内にまとめて定義して、外部ファイル化しない（ただしインラインでは書かない）

- api,config,utilsあたりはプロジェクトごとに必要ない場合もありそうだし、逆にlocal storageを使う場合はstorageみたいなディレクトリがあってもいいかも

じゃあ具体的にどう作っていくかをサクッと解説。

ちなみに開発環境はAtomを使っていて、プラグインは[このエントリ](http://qiita.com/hotchpotch/items/714a0e8f0d364282f95c)見ながら適宜。

react-nativeとeslintはすでにインストールしている前提で。

# 1. init

```
react-native init ProjectName
cd ProjectName
```

# 2. ライブラリのインストール

eslint関連のインストール

```
(
  export PKG=eslint-config-airbnb;
  npm info "$PKG@latest" peerDependencies --json | command sed 's/[\{\},]//g ; s/: /@/g' | xargs npm install --save-dev "$PKG@latest"
)
```

reduxやその他routerのインストール。別にいらない場合はスキップで。

```
npm install --save prop-types react-redux redux react-native-router-flux
```


必要なら, redux-promiseとかredux-sagaとか入れる。

# 3. eslintの設定ファイル作成

設定は適宜。以下は一例。

```
touch .eslintrc.js
vim .eslintrc.js
```

```[.eslintrc.js]
module.exports = {
    "extends": "airbnb",
    "plugins": [
        "react",
        "jsx-a11y",
        "import"
    ],
    "globals": { "fetch": false, "require": false },
    "rules": {
        "react/jsx-filename-extension": [
          1, {
            "extensions": [".js", ".jsx"]
          }
        ],
        "react/prefer-stateless-function": [
          0, { "ignorePureComponents": true}
        ],
        "react/forbid-prop-types": [
          0
        ],
        "no-console": [
          "error", { allow: ["log", "warn", "error"] }
        ],
        "react/no-array-index-key": [
          0
        ],
        "import/prefer-default-export": [
          0
        ],
        "no-constant-condition": [
          0
        ],
        "max-len": [
          0
        ],
        "no-underscore-dangle": [
          0
        ],
        "no-plusplus": [
          0
        ],
        "class-methods-use-this": [
          0
        ],
        "react/jsx-no-bind": [
          0
        ]
    }
};

```

# 4. ディレクトリ構成を作る

```
$ mkdir -p src/api src/config src/utils src/components src/containers/home/screens
$ touch App.js routes.js root.store.js root.reducer.js \
src/containers/home/hoge.reducer.js src/containers/home/home.action.js src/containers/home/home.type.js src/containers/home/screens/index.js
```

# 5. 最低限のファイル作成

Homeのみのページ。

```index.ios.js
import './App';
```

```App.js
import React from 'react';
import { AppRegistry } from 'react-native';
import { Provider } from 'react-redux';

import configureStore from './root.store';
import SampleApp from './routes';

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

AppRegistry.registerComponent('SampleApp', () => App);
```

```root.store.js
import { createStore, applyMiddleware } from 'redux';
import promiseMiddleware from 'redux-promise';
import reducers from './root.reducer';

export default function configureStore() {
  const store = createStore(reducers, applyMiddleware(promiseMiddleware));
  return store;
}
```

```root.reducer.js
import { combineReducers } from 'redux';
import homeData from './src/home/home.reducer';

const rootReducer = combineReducers({
  homeData,
});

export default rootReducer;
```

```src/containers/home/hoge.reducer.js
const initialState = {
};

export default function homeReducer(state = initialState, action) {
  switch (action.type) {
    default:
      return state;
  }
}
```

```src/containers/home/screens/index.js
import React, { Component } from 'react';
import { View, Text } from 'react-native';

class Home extends Component {
  render() {
    return (
      <View>
        <Text>Test</Text>
      </View>
    );
  }
}

export default Home;

```

```routes.js
import React from 'react';
import { Router, Scene } from 'react-native-router-flux';
import Home from './src/containers/home/screens/index';

const App = () => (
  <Router>
    <Scene key="root">
      <Scene key="home" component={Home} title="SampleApp" initial />
    </Scene>
  </Router>
);

export default App;
```

# 参考リンク
- [GitPoint](https://github.com/gitpoint/git-point)
- [ReactNativeでアプリを作る時の個人的な最小構成](http://qiita.com/razokulover/items/7b1b8245d9f56cadf472)
- [http://razokulover.hateblo.jp/entry/2017/08/28/173807](http://razokulover.hateblo.jp/entry/2017/08/28/173807)