与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)
Reducer发送新的可见性过滤器到状态
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函数基本上只是组合两个数组(所有待办事项和具有特定优先级的待办事项),并返回一个唯一元素数组。
问题是当两个复选框都被取消选中时,在这种情况下,我们有不必要的待办事项(例如,如果我们在列表中具有“普通”和“高”优先级的待办事项,并且取消选中“普通”和“低”,则“普通”将重新出现)在列表上。)