score:1

Accepted answer

in the second reducer, you're getting the data from the cats import, instead of from the state! so your reduce is always returning an object from the import instead of from whatever state is passed in. you should not be importing cats in your reducer code.

similarly in your first reducer, you are returning data from the cats import.

in both cases, you should be returning data from the state parameter passed in, not from the cats import.

your first reducer would then look like this:

export default (state = cats, action) => {
  switch(action.type) {
    case 'increment':
      return state.map(cat => cat.name === action.name ? {...cat, clickcount: cat.clickcount + 1} : {...cat});

    default:
      return state;
  }
}

second reducer:

export default (state = cats[0], action) => {
  switch(action.type) {
    case 'set_current_cat':
      return {...state.filter(cat => cat.name === action.name)[0]};
    default: 
      return state;
  }
}

note that the reducer body code references state, not cats. also note that the reducers now return new objects that are clones of the objects in state (not the original objects), using the object spread operator: {...cat} and {...state.filter()[0]}.

it's not necessarily a problem to import cats and use it as the default, though it's not the best design. (the problem is that the code isn't using the state parameter at all, and is instead using the imported object collection.) to avoid using the cats import in the reducers entirely, one option is to pass them in as the default store contents to createstore:

import cats from '../cats';
const defaultstate = { cats, currentcatname: 'lucy' };

const store = createstore(
  rootreducer,
  defaultstate
);

then the defaults for the reducer parameters should return an empty array for the first reducer:

export default (state = [], action) => {

and an empty object for the second reducer:

export default (state = {}, action) => {

another alternative is to add a load_cats action that populates your cat collection, perhaps dispatched on componentdidmount for your top level app component.

another optimization that will help avoid using existing objects is to change set_current_cat to simply change the cat name/id stored in the state:

export default (state, action) => {
      switch(action.type) {
        case 'set_current_cat':
          return action.name;

then to get the current cat, you can add a selector that gets the cat by name/id from the state returned by the first reducer. (adding an id field helps you handle the scenario where there are multiple cats with the same name.) the selector might look like this:

function getcatbyname(state, name) { return state.cats.filter(cat => cat.name === name) }

score:1

you're mutating state when you use the ++ operator on it. use a simple addition instead

 return cats.map(cat => cat.name === action.name ? {...cat, clickcount: cat.clickcount + 1} : cat);

Related Query

More Query from same tag