首页 > 解决方案 > 将全局 redux 存储与组件的本地状态相结合

问题描述

我遇到的挑战是使用全局存储切片,即“流派”,它是一个对象数组,在本地状态下操作复选框的选中/取消选中。当我尝试在初始状态下使用 props.genres 时会出现问题。当本地状态被初始化时,看起来我从 props.genres 得到一个空数组。

const Filters = (props) => {
    const { genres, getSelected, loadGenres, getGenres, clearFilters } = props
    const [isChecked, setIsChecked] = useState(() =>
        genres.map(genre => (
            {id: genre.id, value: genre.name, checked: false}
        ))
    )
    const optionsSortBy = [
        {name: 'Popularity descending', value: 'popularity.desc'},
        {name: 'Popularity ascending', value: 'popularity.asc'},
        {name: 'Rating descending', value: 'vote_average.desc'},
        {name: 'Rating ascending', value: 'vote_average.asc'},
    ]
    const d = new Date()
    let currentYear = d.getFullYear()
    let optionsReleaseDate = R.range(1990, currentYear + 1).map(year => (
        {name: year + '', value: year}
    ))

    useEffect(() => {
        const url = `${C.API_ENDPOINT}genre/movie/list`
        loadGenres(url, C.OPTIONS)
    }, [])

    const handleCheckbox = (e) => {
        let target = e.target
        getGenres(target)
    }

    const handleSelect = (e) => {
        let target = e.target
        let action = isNaN(target.value) ? 'SORT_BY' : 'RELEASE_DATE'
        getSelected(action, target)
    }

    const handleSubmitBtn = (e) => {
        e.preventDefault()
        clearFilters()
    }

    return (
        <form className={classes.FiltersBox}>
            <Submit submited={handleSubmitBtn} />
            <Select name="Sort By:" options={optionsSortBy} changed={handleSelect} />
            <Select name="Release date:" options={optionsReleaseDate} changed={handleSelect} />
            <Genres genres={isChecked} changed={handleCheckbox} />
        </form>
    )
}

const mapStateToProps = (state) => {
    return {
        genres: state.fetch.genres,
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        loadGenres: (url, options) => dispatch(A.getApiData(url, options)),
        getGenres: (targetItem) => dispatch({
            type: 'CHECK_GENRES',
            payload: targetItem
        }),
        getSelected: (actionType, targetItem) => dispatch({
            type: actionType,
            payload: targetItem,
        }),
        clearFilters: () => dispatch({type: 'CLEAR_FILTERS'})
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Filters);
import * as R from 'ramda';
import fetchJSON from '../utils/api.js';

export const getApiData = (url, options) => async (dispatch) => {
    const response = await fetchJSON(url, options)
    const data = response.body
    const dataHas = R.has(R.__, data)
    let actionType = dataHas('genres') ? 'FETCH_GENRES' : 'FETCH_MOVIES'

    dispatch({
        type: actionType,
        payload: data
    })
}
export const fetchReducer = (state = initialState, action) => {
    const { payload } = action
    if (action.type === 'FETCH_GENRES') {
        return {
            ...state,
            isLoading: false,
            genres: [...payload.genres]
        }
    }
    if (action.type === 'FETCH_MOVIES') {
        return {
            ...state,
            isLoading: false,
            movies: [...payload.results]
        }
    }
    return state
}

标签: reactjsreduxuse-stateredux-store

解决方案


你的方法几乎是正确的。当您获取数据时,我不确定状态应该是什么样子。我可以看到mapStateToProps正在尝试访问一开始未定义的值。如果state.fetchundefined你无法访问genres

尝试一:你可以通过使用 lodash.get https://lodash.com/docs/#get来解决 它会赶上undefined问题。

尝试 2:您可以定义一个初始状态,其中您的值是用模拟数据定义的。

const initialState = {fetch: {genres: []}}

并使用它作为你的减速器


推荐阅读