简体   繁体   中英

How to persist data with toggleable state in Redux

I have a TOGGLE_SAVED action in my reducer that I want to both toggle the saved property on a target "image" object (within a loadedImages array), as well as store that object in a savedImages array in state.

I only want one image object in the current loadedImages array to have saved be true as I expect loadedImages to repopulate upon some GET request, while keeping the saved image from the last request in savedImages

Right now my code looks as so:

const initialState = {
    loadedImages: [],
    savedImages: [],
}

const reducer = (state = initialState, action) => {
    switch (action.type) {
        case LOAD_IMAGES:
            return {
                ...state, 
                loadedImages: action.payload, // payload returns a fetch(...)[]
            }
        case TOGGLE_SAVED:
            return {
                ...state,
                loadedImages: state.loadedImages.map(img => {
                    if (img.id === action.payload.id) {

                        return {...img, saved: !img.saved}

                    } else {
                        return {...img, saved: false}
                    }

                }),

                savedImages: [
                    ...state.loadedImages.filter(img => img.saved)
                ]
            } 

        default: 
            return state
    }
}

Right now, savedImages is only populated when TOGGLE_SAVED is ran twice and items within savedImages do not persist over, every time loadedImages is repopulated (via GET request).

Note: a typical "image" object is returned in payload as: {id: 0, saved: Boolean}

I believe in your current reducer, the savedImages prop is actually using the previous reference to loadedImages .

That's why it only works on the second run. You assume that the initial loadedImages map() runs and completes, and then moves on to the next prop, but that is not the case.

What could work is something like this:

case TOGGLE_SAVED:

            const loadedImages = state.loadedImages.map(img => {
                if (img.id === action.payload.id) {
                    return {...img, saved: !img.saved}
                } else {
                    return {...img, saved: false}
            })

            return {
                ...state,
                loadedImages,

                savedImages: [
                    ...loadedImages.filter(img => img.saved)
                ]
            } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM