简体   繁体   中英

redux reducer stops working after an action

I have a backend mongoose database (on Express with NodeJS) with react front. The database consists of one authenticated user (using bcrypt and jwt) and "Shows". Shows can be seen by all, but only authenticated user can post / edit / delete ones.

i'm having trouble with the 'edit show' part. After mongoose finds the correct show to edit, and react shows it, the "shows" reducer stops working completely and if I try to reload the previous page, I'm getting a message that shows.map is not a function. It most probably has something to do with the way I get the one show to load before editing it, but I've tried everything I can think of (state.filter / state.find or just action.show), with no luck. I should add that if I change the return statement under GET_SHOW to just "state", reloading works fine (but of course I don't get the show to edit). I'm using react router for routing but I don't think that's the problem, since everything else works.

the reducer looks like that:

const show = (state = [], action) => {
switch(action.type){

    case GET_SHOW:
    return state.find(show => action.show)

    case LOAD_SHOWS:
    return [...action.shows];

    case EDIT_SHOW:
    return action.show;

    case REMOVE_SHOW:
    return state.filter(show => show._id !== action.id)

    default:
    return state;
}

}

the action to get the show:

 export const load = show => ({
 type: GET_SHOW,
 show
})

export const getShow = (show_id) => (dispatch, getState) =>{
let { setAdmin } = getState();
const id = setAdmin.user.id;
return apiCall("get", `/api/users/${id}/shows/${show_id}/edit`)
.then(res => dispatch(load(res)))
.catch(err => dispatch(addError(err.message)));
}

Thanks in advance for your help!

What exactly do you want to keep in your state object? More than one show or only one?

case GET_SHOW:
return state.find(show => action.show) -> 1

case LOAD_SHOWS:
return [...action.shows]; -> 2

case EDIT_SHOW:
return action.show; -> 3

case REMOVE_SHOW:
return state.filter(show => show._id !== action.id) -> 4

default:
return state;

1) It looks like a buggy line. You're calling find a method which returns the first object which is evaluated as truthy.

In your case, if action.show is truthy, it'll return the first object from the state array.

Consider this example:

const state = [ 'exampleShow1', 'exampleShow2'];
const mockAction = { type: GET_SHOW, show: 'exampleShow3'}

const result = state.find(show => mockAction.show)

The result will be equal 'exampleShow1'

If you want to create a new array with data from an action you can return a new array

return [ action.show]

2) Here you're returning a new array of shows (state is an array)

3) Here you're returning only one show again (state is an object)

4) Here you're returning again array instead of one show. (state is an array)

You need to make your state consistent.

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