React reducers & seamless-immutable

1.9k views Asked by At

I'm new to the whole reducer and immutable thing, so maybe someone can answer me some questions. I'm using seamless-immutable (https://github.com/rtfeldman/seamless-immutable) along with redux-seammless-immutable (https://github.com/eadmundo/redux-seamless-immutable) in a react native app.

I have some questions for the following code:

import { combineReducers } from 'redux-seamless-immutable';
import Immutable from 'seamless-immutable';

const PRODUCTS_INITIAL_STATE = Immutable({ data: Immutable([]), loading: true });

const productsReducer = (state = PRODUCTS_INITIAL_STATE, action) => {
  switch (action.type) {
    case "LOADING":
      return { ...state, loading: action.payload };
    case "LOADED":
      return Immutable.merge(state, {data: Immutable(action.payload) });
    case "ADD_PRODUCT":
      return Immutable.merge(state, {data: Immutable(state.data).concat(action.payload) });
    default:
      return state;
  }
};

const INIT_STORE = Immutable({
  products: productsReducer
});
export default combineReducers(INIT_STORE);
  1. Do I have to define every property as Immutable object like in const PRODUCTS_INITIAL_STATE = Immutable({ data: Immutable([]), loading: true }); or does Immutable take care of that, and it's enough to do a const PRODUCTS_INITIAL_STATE = Immutable({ data: [], loading: true });?
  2. Am I right, that the JSX approach using three dots { ...state, loading: action.payload } is the same as using Immutable.merge?
  3. Is there an easier way for the ADD_PRODUCT action, to add an element to an array that is nested within an object?

Update

Another questions rised: I have an immutable array, that contains objects. When I want to add another element, I have to recreate the array using Immutable(array).concat(newElement). But what if I only want to replace a value inside of one of it's objects?

Consider this array:

const array = Immutable([
  { name: "foo" },
  { name: "bar" }
]);

What's the immutable way to go, if I want to change the name of the first element from foo to hello?

1

There are 1 answers

0
Long Nguyen On

I also new to immutable. But this is my seamless-immutable experience after reading my friend source code.

  1. Do I have to define every property as Immutable object like in const PRODUCTS_INITIAL_STATE = Immutable({ data: Immutable([]), loading: true }); or does Immutable take care of that, and it's enough to do a const PRODUCTS_INITIAL_STATE = Immutable({ data: [], loading: true });?

Yeah, Immutable({ data: [], loading: true }); is just enough. No need nest an immutable object inside immutable.

  1. Am I right, that the JSX approach using three dots { ...state, loading: action.payload } is the same as using Immutable.merge?

{ ...state, loading: action.payload } and state.merge({ loading: action.payload }) is the same, but Immutable.merge will return Immutable object. You can use isImmutable function of seamless-immutable to check whether object is immutable or not.

const demo = Immutable({ foo: 1, bar: "hello" });

console.log("isImmutable", isImmutable({ ...demo, test: 69 }));   // false
console.log("isImmutable", isImmutable(demo.merge({ test: 1 })));   // true
  1. Is there an easier way for the ADD_PRODUCT action, to add an element to an array that is nested within an object?

Something likes this, right?

const PRODUCTS_INITIAL_STATE = Immutable({ data: ['old item'], loading: true });

const newState = state.merge({ data: [...state.data, "new item"] });
  1. What's the immutable way to go, if I want to change the name of the first element from foo to hello?

Simply, just use set api

const array = Immutable([{ name: "foo" }, { name: "bar" }]);

const mutatedArray = array.set(0, { name: "hello" });

Do you have any another questions?