score:2

Accepted answer

you are returning a wrong shape of state in your reducer. your related code:

export default function(state = initialstate, action) { 
    switch (action.type) {
        case get_users:
            return [
                ...state
            ];
        default:
            return state;
    }
}

here, state is an object but you are returning it in an array by spreading it. so, your state gets broken.

try it like that:

case get_users:
    return state;

as @idan dagan pointed out in his answer, actually we do not mutate state in our reducers. i just gave this suggestion since you are just playing around to learn redux and we are returning the original state here, nothing more. but, this is a suitable and better way to return the state:

case get_users:
    return { ...state };

here is a working code: https://codesandbox.io/s/k5ymxwknpv

i also changed foreach with map again as @idan dagan suggested. i haden't realized that. foreach is not the suitable method here since actually it does not return anything. you want to map through your arrays in react and render them.

also, your state name is confusing :) user.users is a little bit weird, you can think a better one maybe.

edit after comments

your get_users action actually is being hit, but you are checking it wrong in your code. you are doing:

export default function(state = initialstate, action) {
  switch (action.type) {
    case get_users:
      return object.assign({}, state);
    default:
      return {
        users: [
          { id: 1, name: "test" },
          { id: 2, name: "test1" },
          { id: 3, name: "test2" }
        ]
      };
  }
}

what happens here? first action of redux is init. this is the initialization of your state. now, since there is no certain action, your reducer hits the default case and returns the test one. now, your state becomes this test data. then your get_users is hit and you return a new object which merges the state which is the test one. here is the steps:

first, state is the `initialstate` -> `init` runs and hits the default case
state is now test one -> get_users hit and returns the `state` which is test one
you see the test one.

how can you test your actions? just put a console.log in your reducer:

export default function(state = initialstate, action) {
  console.log("state",state);
  console.log("action",action);
  .....

and see get_users actually is being hit. the other option is instead of returning the merged object with state, try to merge it with initialstate or with spread operator return a new object by using initialstate:

return return object.assign({}, initialstate);

or

return {...initialstate}

last option provides you a little bit more understanding how my first explanation works. try to return this for your get_users:

return {...state, users:[...state.users, {id:4, name: "foo"}]};

you will see a users list with test data but the last one will be your foo. this explains how you loose your initialstate if you return anything beside state in your default case.

last suggestion, you can debug your redux development with redux dev tools. it is a great tool and does much more than debugging. you can easily track all your operations for redux.

score:0

i'm not sure what are you trying to do with the new state.

but there is couple of changes that you need to do:

  1. use map instead of foreach (because you want to return a new array).
  2. at the reducer you can return the state like this:

export default function(state = initialstate, action) { 
    switch (action.type) {
        case get_users:
            return object.assign({}, state);
        default:
            return state;
    }
}

as mention in redux docs:

we don't mutate the state. we create a copy with object.assign().


Related Query

More Query from same tag