将全局Redux存储与组件的本地状态相结合

时间:2020-04-23 11:38:18

标签: reactjs redux use-state redux-store

我遇到的挑战是在局部状态下使用全局存储片(即“流派”)(即对象数组)来操纵复选框的选中/取消选中。当我尝试在初始状态下使用props.genres时,会发生问题。似乎在初始化本地状态时,我从props.genres中获取了一个空数组。

<div>
  <label for="onoffswitch">
    <span>Toggle dark mode on or off.</span>
  </label>
  <input 
    type="checkbox" 
    name="onoffswitch" 
    id="onoffswitch" 
    onclick="toggleDarkMode()"
  />
</div>
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
    })
}

2 个答案:

答案 0 :(得分:0)

您可以尝试通过props设置状态的初始值,但是这并不能反映最佳实践。考虑将您的数据初始为空数组并通过useEffect操纵状态


 // didn't understand if its array or bool
 const [isChecked, setIsChecked] = useState([])
 useEffect(()=>genres&& {  setIsChecked(... perform action...)
                                 }   ,[genres])

答案 1 :(得分:0)

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

尝试1: 您可以使用lodash.get https://lodash.com/docs/#get解决此问题 它将解决undefined问题。

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

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

并将其用作减速器