首页 > 解决方案 > Redux 使用复选框处理状态

问题描述

使用 React 一段时间后,我最近一直在尝试了解 Redux,但目前我遇到了处理多个复选框的问题。很快,有一个使用 Create-React-app 创建的待办事项列表,我在其中实现了 3 个复选框(默认选中),它们应该按优先级(高、正常、低)显示/隐藏任务。

我尝试通过将操作绑定到复选框来处理它,以显示/隐藏具有不同优先级的任务。

复选框组件 (Checkbox.js)


import React from 'react'
import PropTypes from 'prop-types'

const Checkbox = ({ checked, children, onChange }) => (
  <span>
    <input type = "checkbox" 
       onChange={onChange}
       defaultChecked={true}
       style={{
          marginLeft: '4px',
       }}
       className={'checkbox'}
    />
    {children}
  </span>   
)

Checkbox.propTypes = {
  checked: PropTypes.bool.isRequired,
  children: PropTypes.node.isRequired,
  onChange: PropTypes.func.isRequired
}

export default Checkbox

复选框容器 (Filtercheckbox.js)


import { connect } from 'react-redux'
import { setVisibilityFilter } from '../actions'
import Checkbox from '../components/Checkbox'

const mapStateToProps = (state, ownProps) => ({
  checked: ownProps.filter === state.visibilityFilter
})

const mapDispatchToProps = (dispatch, ownProps) => ({
  onChange: (e) =>  {
                    if(e.target.checked) dispatch(setVisibilityFilter(ownProps.filter[0]))
                    else dispatch(setVisibilityFilter(ownProps.filter[1]))
                }
})

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Checkbox)

父组件中的复选框


<FilterCheckbox filter={[VisibilityFilters.SHOW_HIGH, VisibilityFilters.HIDE_HIGH]}>
        High
</FilterCheckbox>
<FilterCheckbox filter={[VisibilityFilters.SHOW_NORMAL, VisibilityFilters.HIDE_NORMAL]}>
        Normal
</FilterCheckbox>
<FilterCheckbox filter={[VisibilityFilters.SHOW_LOW, VisibilityFilters.HIDE_LOW]}>
        Low
</FilterCheckbox>

Todolist 容器


function getUnique(arr, comp) {
  const unique = arr
  .map(e => e[comp])
  .map((e, i, final) => final.indexOf(e) === i && i)
  .filter(e => arr[e]).map(e => arr[e]);
  return unique;
}

const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case VisibilityFilters.SHOW_ALL:
      return todos
    case VisibilityFilters.SHOW_COMPLETED:
      return todos.filter(t => t.completed)
    case VisibilityFilters.SHOW_ACTIVE:
      return todos.filter(t => !t.completed)
    case VisibilityFilters.SHOW_HIGH:
      return getUnique(todos.concat(todos.filter(t => t.priority === 'High')), 'id')
    case VisibilityFilters.HIDE_HIGH:
        return todos.filter(t => t.priority !== 'High')
    case VisibilityFilters.SHOW_NORMAL:
        return getUnique(todos.concat(todos.filter(t => t.priority === 'Normal')), 'id')
    case VisibilityFilters.HIDE_NORMAL:
        return todos.filter(t => t.priority !== 'Normal')
    case VisibilityFilters.SHOW_LOW:
      return getUnique(todos.concat(todos.filter(t => t.priority === 'Low')), 'id')
    case VisibilityFilters.HIDE_LOW:
        return todos.filter(t => t.priority !== 'Low')
    default:
      throw new Error('Unknown filter: ' + filter)
  }
}

const mapStateToProps = state => ({
  todos: getVisibleTodos(state.todos, state.visibilityFilter)
})

const mapDispatchToProps = dispatch => ({
  toggleTodo: id => dispatch(toggleTodo(id)),
  choosePriority: (id, value) => dispatch(choosePriority(id, value))
})

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

减速器向状态发送新的可见性过滤器


import { VisibilityFilters } from '../actions'

const visibilityFilter = (state = VisibilityFilters.SHOW_ALL, action) => {
  switch (action.type) {
    case 'SET_VISIBILITY_FILTER':
        return action.filter
    default:
      return state
  }
}

export default visibilityFilter

检查复选框时,Todolist容器中的函数GetVisibletodos基本上仅将两个数组(全部与某些优先级的Todos结合在一起),并返回一系列唯一的元素。

问题是当一个接一个地取消选中 2 个复选框时,在这种情况下,我们有不需要的待办事项(例如,如果我们在列表中有正常和高优先级待办事项并取消选中正常然后低,正常的将重新出现在列表中)。

标签: reactjsreact-redux

解决方案


推荐阅读