ReactNativeにStorybookを導入するまで
storybookはコンポーネント単位でサンドボックス開発できる開発環境
どんなコンポーネントが存在するか、どんな種類があるか、使い方は?など
ドキュメントとしても機能するのであると便利
最近Webの方でよく使われてるようで、ReactNativeでも使える
導入
まずはstorybookをグローバルにインストールする
$ npm i -g @storybook/cli
RNのプロジェクトに移動してgetstorybook
を実行
$ getstorybook
あとは勝手に設定されて
storybook
というフォルダが作成される
最初からいくつかサンプルコードが入っているので実行して確認してみる
実行
ReactNativeの場合、コンポーネントの動作はシュミレーター上で確認するので
既にアプリが起動してる場合は、いつも動かしてる8081のサーバーは落としておく必要がある
まずはstorybookのサーバーを起動
$ yarn run storybook
localhost:7007
にアクセスすると専用のページが表示される
この時点では、リストに何も表示されてなくてサンプルを確認出来ない
RNのアプリを立ち上げると、さっき起動したstorybookのサーバーに繋がって
アプリ側にも専用の画面が表示される
するとWebの画面にも用意したコンポーネントのリストが表示されるようになり
見たい項目をクリックすると、連動してシュミレーター上でも画面が切り替わる
これでやっと確認出来るようになった
※ 左の画面がiOSシュミレーター
最初からあるサンプルを参考に自分のアプリのコンポーネントも追加していけば
これでチーム開発も捗るのではないだろうか
今回動かしたのサンプル:GitHub - rskull/rn_storybook
でもシュミレーター上で確認しないといけないのはちょっと面倒くさいかも…
以上です
ミドルウェアを使わないreduxをちゃんと理解するための個人メモ
仕事でいきなりredux/redux-saga
さらに redux-actions
の環境を触ってきて
ミドルウェアを使わないシンプルな構成のreduxの理解が浅かったのでちゃんと覚えようと思った
環境構築
お手軽 create-react-app
$ create-react-app react-redux-example
次にreduxを使うのに必要なnpmモジュールをインストールする
$ yarn add redux react-redux
react-redux
は react
で redux
を扱うために必要
これだけで環境は整った
処理の流れ
ActionType
ただの変数
イベントの名前を付けてく
const ADD_ITEM = 'ADD_ITEM' const DELETE_ITEM = 'DELETE_ITEM'
Action
オブジェクトを返すだけのピュアな関数
typeを設定するのはお約束
// typeにActionTypeを設定 export const addItem = item => ({ type: ADD_ITEM, item }) export const deleteItem = id => ({ type: DELETE_ITEM, id }) // addItem('hello') // -> { type: 'ADD_ITEM', item: 'hello' }
Reducer
storeの構造はここで決まる
import { combineReducers } from 'redux' // 初期値 const initialState = [ { item: 'hello' } ] const todos = (state = initialState, action) => { switch (action.type) { // アイテムを追加 case ADD_ITEM: return [...state, { item: action.item }] // アイテムを削除 case DELETE_ITEM: return state.filter((v, k) => k !== action.id) default: return state } } // 分割されたreducerを合成 // これがstore全体の構造になる const reducer = combineReducers({ todos })
Storeを生成
import { createStore } from 'redux' // 前述のReducersで生成した値が入る const store = createStore(reducer)
ミドルウェアがある場合はcreateStoreの第2引数に設定を渡すが
今回は素のredux構成なので省略
描画する
index.js
を編集
import { Provider } from 'react-redux' // ... ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ) // ...
ここでやっとreact-redux
が登場
storeの値やActionが使えるようになる
App.js
container
となるものは全てこの形式で書かれる
import { connect } from 'react-redux' class App extends Component<{}> { render() { const { todos, actions } = this.props return ( <div> <button onClick={() => actions.addItem('world')}>ADD</button> <ul> {todos.map((v, k) => <li onClick={() => actions.deleteItem(k)}>{v.item}</li>)} </ul> </div> ) } } // stateにstoreの値が入ってる // this.props.todosで使えるようになる const mapStateToProps = state => ({ todos: state.todos }) // Actionsで定義した関数が使えるようになる // this.props.actions.addItem('hello') const mapDispatchToProps = dispatch => ({ actions: bindActionCreators(Actions, dispatch) }) // Appコンポーネントに各値を接続 export default connect(mapStateToProps, mapDispatchToProps)(App)
まとめ
処理の流れが分かってスッキリした
今回のソース
わかりやすいように出来るだけ1ファイルに納めて書いてる
次はミドルウェア
を導入してどう変わっていくかを確かめる
※追記
タイトル変えました
以上
igniteでモダンなReactNative環境を楽々セットアップ
react-native init app
でアプリを始めても最初はredux
やmiddleware
など
いつも決まって使うような環境は入っていない
とりあえず試したいけど面倒くさいよ!って時はignite
コマンドを使うと
定番の環境、いわゆるボイラープレートをいい感じに構築してくれる
そうでない人も、個人的にフォルダ構成や書き方は参考になった
準備
react-native
まずはReactNativeを動かせる環境を作る
Getting Started - React Native
$ brew install node $ brew install watchman $ npm install -g react-native-cli
ignite
ignite
をインストール
$ npm install -g ignite-cli
ignite
コマンドを使うと
対話形式で定番のライブラリを導入するか聞かれていき
最後に全て設定が整ったプロジェクトが生成される
この生成されるボイラープレートには種類があり
下のリンクで配布されている中から -b
で指定出来る
ignite/BOILERPLATES.md at master · infinitered/ignite · GitHub
また、自分でボイラープレートを作成することも出来る
ignite/creating-boilerplates.md at master · infinitered/ignite · GitHub
$ ignite new MyNewAppName -b ir-boilerplate
何もなも指定しないと、デフォルトで redux/redux-saga
がメインの構成になる
試す
$ ignite new igniteApp
実行した後、いくつか質問されます
- Would you like Ignite Development Screens?
- 動いてるサンプルが見たい場合は
yes
- 動いてるサンプルが見たい場合は
- What vector icon library will you use?
- 用意された様々なiconを表示出来るツールが使いたい場合は
yes
- 用意された様々なiconを表示出来るツールが使いたい場合は
- What internationalization library will you use?
- 多言語対応したい場合は
yes
- 多言語対応したい場合は
- What animation library will you use?
- 便利なアニメーション ライブラリが使いたい場合は
yes
- 便利なアニメーション ライブラリが使いたい場合は
とりあえず全部yes
にする
すると以下のようなフォルダが生成される
├── App │ ├── Components │ ├── Config │ ├── Containers │ ├── Fixtures │ ├── I18n │ ├── Images │ ├── Lib │ ├── Navigation │ ├── Redux │ ├── Sagas │ ├── Services │ ├── Themes │ └── Transforms │ ├── README.md ├── Tests ├── android ├── app.json ├── ignite ├── index.js ├── ios ├── node_modules ├── package.json ├── storybook └── yarn.lock
storybookもデフォルトで設定されてて嬉しい
起動
$ react-native run-ios
コンポーネント・API・テーマ・画面遷移など、サンプルコードが一式確認出来るので
とりあえずコードを眺めたりいじったりしてみると良いのではないでしょうか
時間があったら自分用のボイラープレート作ってみる予定
以上
ReactNativeのAsyncStorageをコンソールから直接操作する
前回の記事で導入したReact Native Debugger
を使うと
AsyncStorage
を直接操作することが出来る
AsyncStorageとは
アプリ本体にデータを保存したい時に使えるkey-valueストア
永続化されるのでアプリを落としてもデータが保持される
実際にはSQLiteをラップしてるっぽい
AsyncStorage
をラップしてプロミスを返すようにしたこのモジュールがおすすめ
ちょっと書きやすくなってる
直接操作する
一度データを保存すると、後で消したりデバッグするのが面倒くさい
そこでReact Native Debugger
を使うとコンソールから直接操作することが出来る
const store = require('AsyncStorage') // 指定したキーを削除する store.removeItem('key') // 値をセットする store.setItem('key', 'hello!')
とくに特別なことしてるわけではなく、普通にAsyncStorage
をインポートして直接操作してるだけ
他の細かい操作はドキュメントを参照
本当はGUIで操作したいけど、そんな方法があれば知りたい
以上