0

if i pull some data from an external source fro the initial state, then want to add additional information like for example 'liked'? i've tried adding to the products array but its go messy, I'm thinking i should have an additional array for liked items then put the product id in this, the only thing is i need it to reflect in the product that it has been liked and I'm mapping the product data to the item.

whats the best way to go about this ?

const initialState = {
  isFetching: false,
  products: [],
};

should i add favs: [] ?

how would i reflect the liked state to my product as I'm mapping the products array to the product component? and the liked state is now in the favs?

i tried doing this to add it to the product array but it got really messy (something like this)

case ADD_LIKED:
 state.products[action.index]['liked'] = true;
 return state;
2
  • reducer it's a pure function. Instead of mutating states(in your case it's a array) you should return new states with existing array plus new data Commented Dec 3, 2015 at 18:56
  • yeah i knew it was wrong, it was more just to express what i was trying to achieve. Commented Dec 3, 2015 at 21:20

1 Answer 1

1
state.products[action.index]['liked'] = true;

The problem here is that you are mutating the state inside the reducer which is one of the things you should never do inside a reducer.

You'll find that writing functions which don't mutate the data are much easier if you break them down into smaller parts. For instance you can start to split your application up.

function productsReducer(products = [], action) {
  // this reducer only deals with the products part of the state.
  switch(action) {
    case ADD_LIKED:
      // deal with the action
    default:
      return products;
  }
}

function app(state = {}, action) {
  return {
    isFetching: state.isFetching,
    products: productsReducer(state.products, action)
  }
}

In this case I would definitely want to write a little immutability helper.

function replaceAtIndex(list, index, replacer) {
  const replacement = replacer(list[index]);

  const itemsBefore = list.slice(0, index),
        itemsAfter = list.slice(index + 1);

  return [...itemsBefore, replacement, ...itemsAfter];
}

You can complement this with a generic function for changing objects in lists.

function updateInList(list, index, props) {
  return replaceAtIndex(list, index, item => {
    return { ...props, ...item };
  });
}

Then you can rewrite your function in the immutable form

 switch(action) {
    case ADD_LIKED:
      return updateInList(products, action.index, { liked: true });
    default:
      return products;
  }

You could even get fancy by partially applying the function. This allows you to write very expressive code inside your reducers.

 const updateProduct = updateInList.bind(this, products, action.index);

 switch(action) {
    case ADD_LIKED:
      return updateProduct({ liked: true });
    case REMOVE_LIKED:
      return updateProduct({ liked: false });
    default:
      return products;
  }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.