1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Expo+Redux(+firebase)でログインフォーム③ 〜ファイル整理・Debugger〜

Last updated at Posted at 2020-02-20

はじめに

Expo+Redux(+firebase)でログインフォーム② 〜Reduxの導入〜 の続きです。
この記事では、Ducksパターンを意識してReduxの各部品をファイルに分けていき、ReactNativeDebuggerを使えるようにするまでを扱います。

ファイル分割後のディレクトリ構成

root/
  ├ src/
      ├ App.tsx
      ├ store.ts
      ├ Styles.ts
      ├ components/
           ├ Counter.tsx
      ├ containers/
           ├ Counter.ts
      ├ modules/
           ├ index.ts
           ├ CounterModule.ts
  ├ node_modules/
  ├ package.json

ファイル分割

ほぼ、前回の記事のApp.tsxを分割しただけです。

App

src/App.tsx
import React from 'react';
import { Provider } from 'react-redux'
import store from './store'
import CounterContainer from './containers/Counter'

export default function App() {
  return (
    <Provider store={store}>
        <CounterContainer />
    </Provider>
  )
}

Store

src/store.ts
import { createStore, combineReducers } from 'redux'
import { counterModule } from './modules'

const store = createStore(
  combineReducers({ count: counterModule.counter })
)

export default store

Style

src/Styles.ts
import { StyleSheet } from 'react-native'

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
  paragraph: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
  },
})

export default styles

これはなくてもいいですが、スタイルをつけなければ画面左上に要素が集まってしまい、見にくいですね。

Component

src/components/Counter.tsx
import React from 'react'
import { View, Text, Button } from 'react-native'
import styles from '../Styles'

const Counter = ({ count, increment, decrement }) => (
  <View style={styles.container}>
    <Text style={styles.paragraph}>{count}</Text>
    <Button
      title='Increment'
      onPress={increment}
    />
    <Button
      title='DECREMENT'
      onPress={decrement}
    />
  </View>
)

export default Counter

ReactのPresentational Componentです。
Buttonが押下された時に呼ばれる関数は下記のContainerに実装しておき、propsで渡すようにしています。ロジックはComponentには書かないほうがいいらしいです。

Container

src/containers/Counter.ts
import { connect } from 'react-redux'
import { counterModule } from '../modules'
import Counter from '../components/Counter'

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

const mapDispatchToProps = dispatch => {
  return ({
    increment: () => dispatch(counterModule.increment()),
    decrement: () => dispatch(counterModule.decrement())
  })
}

const CounterContainer = connect(mapStateToProps, mapDispatchToProps)(Counter)
export default CounterContainer

mapStateToProps, mapDispatchToPropsを定義して、connectを使ってComponentに渡しています。
今回は使わないですが、複雑なロジックが必要なら、これにmergePropsを加えるのがいいらしいです。

Module

src/modules/index.ts
import CounterModule from './CounterModule'

export const counterModule = new CounterModule()

moduleをまとめています。今後moduleが多くなっていくと、ここに追加していく感じです。

src/modules/CounterModule.ts
export default class CounterModule {
  // reducer
  counter(state, action) {
    if (action.type === 'undefined') {
      return null
    }

    switch(action.type) {
      case 'INCREMENT':
        return state + 1
      case 'DECREMENT':
        return state - 1
      default:
        return null
    }
  }

  // actionCreator
  increment = () => {
    return { type: 'INCREMENT' }
  }

  decrement = () => {
    return { type: 'DECREMENT' }
  }
}

actionTypeも作った方がいいんでしょうが、なんとなく省いています笑

React Native Debugger

このままではreduxがちゃんと動いているのか分かりにくいので、デバッガーを使いたいと思います。
こちらの記事を参考にさせてもらったのですが、そのままだと動かなかったので少し修正します。

Storeを修正

src/store.ts
import { createStore, combineReducers, compose, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { counterModule } from './modules'

const composeEnhancer = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose

const store = createStore(
  combineReducers({ count: counterModule.counter }),
  composeEnhancer(applyMiddleware(thunk))
)

export default store

このようにミドルウェアのredux-thunkを挟まないと、デバッガが繋がらないみたいです(僕もよくわかっていない笑)

デバッガをインストール、起動

インストール

brew update && brew cask install react-native-debugger

起動

open "rndebugger://set-debugger-loc?host=localhost&port=19001"

はじめ、シングルクォーテーション(')で囲っていたのですが,なぜかエラー

The file /Users/atsushi/myProjects/react-navigation-redux/‘rndebugger:/set-debugger-loc?host=localhost does not exist.
[1]+  Exit 1                  open ‘rndebugger://set-debugger-loc?host=localhost
~

が出たので、ダブルクォーテーション(")で囲い直して見ると、うまくいきました。
image.png

次回

次回は、React Navigationを用いて画面遷移を実装していきます。
いよいよサインイン、サインアップ画面を作っていくことになります。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?