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

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

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

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

github

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

参考にしたのはこちらの2つ
公式サイト

いつもお世話になってます…

今回作るもの

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

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

##まずはお試し

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,
  }
});  

ここまでできるとこんな感じになります。
react-nativeでiOSアプリ開発者に! 第10回 redux(todoappその3)

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

 

react-nativeでiOSアプリ開発者に! 第10回 redux(todoappその3)
他のボタンを押すとアクティブでないタスクが表示されることが確認できます。

 

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

 

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とかで代用できないですかね?
知ってたら誰かおしえて下さい。

PR

Instagram Feed

Load More
Something is wrong. Response takes too long or there is JS error. Press Ctrl+Shift+J or Cmd+Shift+J on a Mac.

Instagram

専務取締役

funatsukeisuke

WEBと教育を組み合わせて何かおもしろいことをやってやろうと画策しています。AWESOMEでは開発を担当、個別指導塾コミットでは塾長と2足の草鞋を履きながら日々勉強しています。

他の投稿を見る →