[Functional Programming + React] Provide a reasonable default value for mapStateToProps in case initial state is undefined

For example we have a component, it needs to call 'react-redux' connect function.

import { compose, curry, option, propPath } from '../js/helper'

const FilterButton = ({ active, onClick }) => {
    const classes = classnames('filterButton', {
        'filterButton--active': active
    })
    return <Button className={classes} onClick={onClick} icon={faFilter} />
}

FilterButton.defaultProps = {
    active: true,
    onClick: Function.prototype
}

FilterButton.propTypes = {
    active: PropTypes.bool,
    group: PropTypes.string.isRequired,
    onClick: PropTypes.func
}

const mapStateToProps = (state, ownProps) => ({
    active: state.ui.filterGroups[ownProps.group]
})

export default connect(mapStateToProps)(FilterButton)

For the hightlighted part, there can be many possible reason for it to go wrong. We can use Maybe to provide a reasonable default value.

First, the inital State is:

const data = {
    nextId: 4,
    todoFilter: 'SHOW_ALL',
    todos: [
       ...
    ],
    ui: {
        filterGroups: {
            status: false
        }
    }
}

If the highlighted part is undefined, we still want it works.

import { compose, curry, option, propPath } from 'crocks'
...

const activeGroup = curry(group =>
    compose(
        option(FilterButton.defaultProps.active),
        propPath(['ui', 'filterGroups', group])
    )
)
const mapStateToProps = (state, ownProps) => ({
    active: activeGroup(ownProps.group, state)
})

export default connect(mapStateToProps)(FilterButton)

--Full code--

import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import Button from './controls/Button'
import classnames from 'classnames'
import { faFilter } from '@fortawesome/free-solid-svg-icons'

import { compose, curry, option, propPath } from 'crocks'

const FilterButton = ({ active, onClick }) => {
    const classes = classnames('filterButton', {
        'filterButton--active': active
    })
    return <Button className={classes} onClick={onClick} icon={faFilter} />
}

FilterButton.defaultProps = {
    active: true,
    onClick: Function.prototype
}

FilterButton.propTypes = {
    active: PropTypes.bool,
    group: PropTypes.string.isRequired,
    onClick: PropTypes.func
}

const activeGroup = curry(group =>
    compose(
        option(FilterButton.defaultProps.active),
        propPath(['ui', 'filterGroups', group])
    )
)

const mapStateToProps = (state, ownProps) => ({
    active: activeGroup(ownProps.group, state)
})

export default connect(mapStateToProps)(FilterButton)

猜你喜欢

转载自www.cnblogs.com/Answer1215/p/10727119.html