title: Redux handling state with checkboxes
body: <p>Having worked with React for some time, I have been trying to understand Redux a little bit more recently, and currently I'm stuck on a problem of handling multiple checkboxes. Shortly, there is a todo-list created with Create-React-app where I implemented 3 checkboxes (checked by default) which should show/hide tasks by priority (High, Normal, Low).</p>
  
  <p>I have tried handling it with binding actions to checkboxes to show/hide tasks with different priorities. </p>
  
  <p>Checkbox component (Checkbox.js)</p>
  
  <pre><code>
  import React from 'react'
  import PropTypes from 'prop-types'
  
  const Checkbox = ({ checked, children, onChange }) =&gt; (
    &lt;span&gt;
      &lt;input type = "checkbox" 
         onChange={onChange}
         defaultChecked={true}
         style={{
            marginLeft: '4px',
         }}
         className={'checkbox'}
      /&gt;
      {children}
    &lt;/span&gt;   
  )
  
  Checkbox.propTypes = {
    checked: PropTypes.bool.isRequired,
    children: PropTypes.node.isRequired,
    onChange: PropTypes.func.isRequired
  }
  
  export default Checkbox
  </code></pre>
  
  <p>Checkbox container (Filtercheckbox.js)</p>
  
  <pre><code>
  import { connect } from 'react-redux'
  import { setVisibilityFilter } from '../actions'
  import Checkbox from '../components/Checkbox'
  
  const mapStateToProps = (state, ownProps) =&gt; ({
    checked: ownProps.filter === state.visibilityFilter
  })
  
  const mapDispatchToProps = (dispatch, ownProps) =&gt; ({
    onChange: (e) =&gt;  {
                      if(e.target.checked) dispatch(setVisibilityFilter(ownProps.filter[0]))
                      else dispatch(setVisibilityFilter(ownProps.filter[1]))
                  }
  })
  
  export default connect(
    mapStateToProps,
    mapDispatchToProps
  )(Checkbox)
  </code></pre>
  
  <p>Checkboxes in parent component</p>
  
  <pre><code>
  &lt;FilterCheckbox filter={[VisibilityFilters.SHOW_HIGH, VisibilityFilters.HIDE_HIGH]}&gt;
          High
  &lt;/FilterCheckbox&gt;
  &lt;FilterCheckbox filter={[VisibilityFilters.SHOW_NORMAL, VisibilityFilters.HIDE_NORMAL]}&gt;
          Normal
  &lt;/FilterCheckbox&gt;
  &lt;FilterCheckbox filter={[VisibilityFilters.SHOW_LOW, VisibilityFilters.HIDE_LOW]}&gt;
          Low
  &lt;/FilterCheckbox&gt;
  </code></pre>
  
  <p>Todolist container</p>
  
  <pre><code>
  function getUnique(arr, comp) {
    const unique = arr
    .map(e =&gt; e[comp])
    .map((e, i, final) =&gt; final.indexOf(e) === i &amp;&amp; i)
    .filter(e =&gt; arr[e]).map(e =&gt; arr[e]);
    return unique;
  }
  
  const getVisibleTodos = (todos, filter) =&gt; {
    switch (filter) {
      case VisibilityFilters.SHOW_ALL:
        return todos
      case VisibilityFilters.SHOW_COMPLETED:
        return todos.filter(t =&gt; t.completed)
      case VisibilityFilters.SHOW_ACTIVE:
        return todos.filter(t =&gt; !t.completed)
      case VisibilityFilters.SHOW_HIGH:
        return getUnique(todos.concat(todos.filter(t =&gt; t.priority === 'High')), 'id')
      case VisibilityFilters.HIDE_HIGH:
          return todos.filter(t =&gt; t.priority !== 'High')
      case VisibilityFilters.SHOW_NORMAL:
          return getUnique(todos.concat(todos.filter(t =&gt; t.priority === 'Normal')), 'id')
      case VisibilityFilters.HIDE_NORMAL:
          return todos.filter(t =&gt; t.priority !== 'Normal')
      case VisibilityFilters.SHOW_LOW:
        return getUnique(todos.concat(todos.filter(t =&gt; t.priority === 'Low')), 'id')
      case VisibilityFilters.HIDE_LOW:
          return todos.filter(t =&gt; t.priority !== 'Low')
      default:
        throw new Error('Unknown filter: ' + filter)
    }
  }
  
  const mapStateToProps = state =&gt; ({
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  })
  
  const mapDispatchToProps = dispatch =&gt; ({
    toggleTodo: id =&gt; dispatch(toggleTodo(id)),
    choosePriority: (id, value) =&gt; dispatch(choosePriority(id, value))
  })
  
  export default connect(
    mapStateToProps,
    mapDispatchToProps
  )(TodoList)
  </code></pre>
  
  <p>Reducer sending new visibility filter to state</p>
  
  <pre><code>
  import { VisibilityFilters } from '../actions'
  
  const visibilityFilter = (state = VisibilityFilters.SHOW_ALL, action) =&gt; {
    switch (action.type) {
      case 'SET_VISIBILITY_FILTER':
          return action.filter
      default:
        return state
    }
  }
  
  export default visibilityFilter
  </code></pre>
  
  <p>When a checkbox is checked the function getVisibleTodos in the Todolist container basically just combines two arrays (all todos with todos of certain priority) and returns an array of unique elements.</p>
  
  <p>The problem is when 2 checkboxes are unchecked one after another, in that case we have got unwanted todos (for example, if we have Normal and High priority todos in the list and uncheck Normal and then Low, the Normal ones will reappear on the list).</p>