ローディング中

react-nativeでiOSアプリ開発者に! 第10回 redux(todoappその3)

みなさんこんにちは、個別指導塾コミット塾長、AWESOME開発担当の船津です。

まだまだ全然ES6のアロー関数を使いこなせずにいます。結局function(){…}となっている方が見易いもので…
thisのスコープが変わるらしいのでアロー関数使ったほうが良い場面もあるのでしょうが、なかなか難しいですね。
ではでは始めていきます。

目次

今回のバージョンのgithubリポジトリ

github

今回はTodoリストらしく、「完了」、「未完了」を区別して表示、非表示を選択できるようにしましょう。

参考にしたのはこちらの2つ
公式サイト
http://redux.js.org/docs/basics/ExampleTodoList.html

いつもお世話になってます…
http://qiita.com/xkumiyu/items/1ba476b8043b71561f52

今回作るもの

今回は前回のまでの機能に少し手を加えていきます。
変更点のみ記述していきます。

それでは作っていきましょう。

##まずはお試し

actions/index.js

  • 以下を追記しましょう
  • タスクを表示するしないを判別するsetVisibilityFilterのactionを発行します。
  • ‘SHOW_ALL’等の文字列を引数として受け取ります。
export const setVisibilityFilter = (filter) => {
  return {
    type: 'SET_VISIBILITY_FILTER',
    filter
  }
}

reducers/visibilityFilter.js

  • 発行されたアクションに対する処理を記述します。
  • フィルターの内容を返すだけの関数です。
  export default function visibilityFilter(state = 'SHOW_ACTIVE', action) {
  switch(action.type){
    case 'SET_VISIBILITY_FILTER':
      return action.filter
    default:
      return state
  }  
}

conatainers/TodoApp.js

  • todosとfilterをmapStateToPropsに渡して一括で受け取れるようにします。
  • 詳しくは公式サイトで(まだあんまりわかってない)
function getVisibleTodos(todos, filter) {
  switch(filter) {
    case 'SHOW_ALL':
      return todos
    case 'SHOW_COMPLETED':  
      return todos.filter((t) => t.completed)
    case 'SHOW_ACTIVE':  
     return todos.filter((t) => !t.completed)
  }
}

function mapStateToProps(state) {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  }
}

動作を確かめてみよう

以下を追記して動作を確かめてみましょう。
テストするときだけlet store =となっているところからletを消して、storeをグローバルにしておきましょう。

containers/TodoList.js

  • 実際にstore.dispatch(setVisibilityFilter('SHOW_ALL'))等を実行してみましょう。
    <View style={styles.toggle}>
        <TouchableHighlight onPress={() => {
              store.dispatch(setVisibilityFilter('SHOW_ALL'))
              console.log(store.getState())
            }}
        activeOpacity={75 / 100}
        underlayColor={"rgb(210,210,210)"}>
        <Text>show all</Text>        
      </TouchableHighlight>  
        <TouchableHighlight onPress={() => {
              store.dispatch(setVisibilityFilter('SHOW_COMPLETED'))
              console.log(store.getState())
            }}
        activeOpacity={75 / 100}
        underlayColor={"rgb(210,210,210)"}>
        <Text>show completed</Text>        
      </TouchableHighlight>  
      <TouchableHighlight onPress={() => {
              store.dispatch(setVisibilityFilter('SHOW_ACTIVE'))
              console.log(store.getState())
            }}
        activeOpacity={75 / 100}
        underlayColor={"rgb(210,210,210)"}>
        <Text>show active</Text>        
      </TouchableHighlight>  
     </View>   
 
--- 
     
 const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    flexDirection: 'column',
  },
  input: {
    height: 30, 
    width: 100,
    borderWidth: 1,
    borderColor: "rgba(0,0,0,0.5)",
    borderRadius: 5,
    textAlign: 'center',
  },
  inputarea: {
    flex: 1,
    justifyContent: 'center',
  },
  toggle: {
    flex: 1,
  }
});  

ここまでできるとこんな感じになります。
Screen Shot 2016-08-17 at 17.21.49

デフォルトではアクティブなタスクのみ表示されるので、タスクを押すと表示されなくなります。

 

Screen Shot 2016-08-17 at 17.22.59
他のボタンを押すとアクティブでないタスクが表示されることが確認できます。

 

Screen Shot 2016-08-17 at 17.23.16

 

store.dispatch(setVisibilityFilter(‘SHOW_ACTIVE’)とかやってる部分をすっきりさせましょう

その前に

テストも終わったので
storeの頭にletを付けておきましょう。

containers/TodoApp.js

  • store.dispatch(setVisibilityFilter('SHOW_ACTIVE')みたいなのをfilterTodo('SHOW_ACTIVE')で呼び出せるようにします。
  • 親コンポーネントからTodoListコンポーネントにfilterTodoを渡します。

 render() {
    const { todos, submitTask, onTodoClick, filterTodo } = this.props;
      return (
        <TodoList todos={todos} submitTask={submitTask} onTodoClick={onTodoClick} filterTodo={filterTodo} />
    )
  }

function mapDispatchToProps(dispatch) {
  return {
    submitTask: (text) => {
      dispatch(addTodo(text))
    },
    onTodoClick: (id) => {
      dispatch(toggleTodo(id))
    },
    filterTodo: (filter) => {
      dispatch(setVisibilityFilter(filter))
    },
  }
}

components/TodoList.js

  • 受け取ったfilterTodo(filter)store.dispatch(setVisibilityFilter(filter)と差し替えます。

const { todos, submitTask, onTodoClick, filterTodo} = this.props;

 <View style={styles.toggle}>
  <TouchableHighlight onPress={() => filterTodo('SHOW_ALL')}
  activeOpacity={75 / 100}
  underlayColor={"rgb(210,210,210)"}>
  <Text>show all</Text>        
</TouchableHighlight>  
  <TouchableHighlight onPress={() => filterTodo('SHOW_COMPLETED')}
  activeOpacity={75 / 100}
  underlayColor={"rgb(210,210,210)"}>
  <Text>show completed</Text>        
</TouchableHighlight>  
<TouchableHighlight onPress={() => filterTodo('SHOW_ACTIVE')}
  activeOpacity={75 / 100}
  underlayColor={"rgb(210,210,210)"}>
  <Text>show active</Text>        
</TouchableHighlight>    
   </View> 

次の課題

  • アクションが増えてくると管理するのが面倒なのでミドルウェアを入れる?
  • コンポーネント、関数をもっとまとめられそう

とりあえず写経します!!

Todoリストはおしまい?

おしまいですが、そのうちいままでの仕組みとDBを組み合わせてよりアプリらしくしていこうかなと思います。
realmとかっていうのが検索に引っかかるんですが、そんな大きなデータじゃないのでAsyncStorageとかで代用できないですかね?
知ってたら誰かおしえて下さい。

ホームページ・デザイン制作のご相談・ご依頼は

079-451-5881

68ED4C65-BA1E-46D0-A7AC-B9869923C696 Created with sketchtool. A07C553F-CF16-4B7D-94FE-D36AE0A6297D Created with sketchtool. 37B7D8F4-7A18-4725-9EC6-595ABDF69D64 Created with sketchtool. 95DFB680-1EDF-4199-BC4A-BB6752EBA23C Created with sketchtool. 02DDF754-E1DB-4EF2-B6BB-C884722938C4 Created with sketchtool. NEW! 1A95E369-6469-4C46-B38F-F83410B928B0 Created with sketchtool. Group 5Group 2Group 4Group 3E4FC8CF2-721D-4699-8162-18E886C432C1 Created with sketchtool.