I have just started of with ImmutableJS and I want to make an reducer Immutable. I've read that I need to convert my reducer back in order for this to work. Anyone that could e up with an answer of how to make this work? Per se I get the error message: "INCREASE_NUMBER.toObject() is not a function" Here's the code(below) :
import { INCREMENT } from '../actionTypes/default'
import { Map, toObject } from 'immutable'
const INCREASE_NUMBER = (state = Map({number: 0}), action) => {
switch(action.type) {
case INCREMENT:
return state.merge({number: state.number + 1})
default:
return state
}
};
INCREASE_NUMBER.toObject()
module.exports = INCREASE_NUMBER
I have just started of with ImmutableJS and I want to make an reducer Immutable. I've read that I need to convert my reducer back in order for this to work. Anyone that could e up with an answer of how to make this work? Per se I get the error message: "INCREASE_NUMBER.toObject() is not a function" Here's the code(below) :
import { INCREMENT } from '../actionTypes/default'
import { Map, toObject } from 'immutable'
const INCREASE_NUMBER = (state = Map({number: 0}), action) => {
switch(action.type) {
case INCREMENT:
return state.merge({number: state.number + 1})
default:
return state
}
};
INCREASE_NUMBER.toObject()
module.exports = INCREASE_NUMBER
Based on your question, it seems like you don't really understand immutability all that well and I therefore question the legitimacy of your need to use ImmutableJS in the first place. You don't have to use ImmutableJS to write non-mutating state transformations.
I don't need outlet covers to prevent myself from poking metal objects into the electrical outlet. I'd rather not be electrocuted, so I don't go poking things into the outlet all willy nilly. It's not anymore plicated than that.
You're better off developing an intimate understanding of the tools you're working with. You should know when JavaScript operators/functions/methods are mutating data and when they're not. If you think ImmutableJS can protect you from your own ignorance, you'll be making a big mistake. You'll run into problems at some point and have no idea how to diagnose them because you didn't take the time to understand what you're doing.
Your reducer can be written with no-nonsense vanilla JavaScript
import { INCREMENT } from '../actionTypes/default'
const initialState = {number: 0}
const increaseNumberReducer = (state, action) => {
switch (action.type) {
case INCREMENT:
return {number: state.number + 1}
default:
return state
}
}
export default increaseNumberReducer
No mutations here. Mutation is fundamentally impossible the way this code is written. We are reading a value from state
but there is no code here that could write to the existing state
object. state
is not an immutable object, but you're not a dumb developer either. If you wrote some code to mutate the state
object, that's your own fault. You only have yourself to blame if you go poking around in the electrical outlet.
I could have just as easily wrote
// non-mutating state transformation
case INCREMENT:
return Object.assign({}, state, {number: state.number + 1})
... and you should know how that differs from
// mutating state transformation
case INCREMENT:
return Object.assign(state, {number: state.number + 1})
Likewise, you should know the difference between
// non-mutating array transformation
[1,2,3].concat([4])
... and this
// mutating array transformation
[1,2,3].push(4)
And how about this
// mutating sort
[4,2,1,3].sort()
... and this
// non-mutating sort
[4,2,1,3].slice(0).sort()
Sure, if you had a big app, someone might argue it'd make sense to add a small immutability safety precaution around your data. This might prevent ignorant developers from accidentally mutating state
when they're not supposed to. To me, this isn't a valid solution tho. If this is a redux app, your developers should have intimate knowledge of redux philosophy, and that means that reducers are pure functions and state
is never to be mutated... There is no substitute for knowledge and wisdom.
Come to know JavaScript intimately. Learn the tools you're working with. Identify the pros and cons of various methods. Understand the "costs" of various techniques. Know when and where you can make promises. If you still decide to use ImmutableJS at the end of all that, you'll know why you chose it and you'll know the gains/losses that e with it.
The reducer is a function - a pure function that does not hold on to any state. E.g. immutability does not make sense in terms of a reducer.
Immutability refers to data structures, not functions. In React and Redux, it is a good practice to make your state immutable, e.g. design your reducer functions in a way that they always return immutable data structures. But this does not apply to the reducer itself - that's just a function.
import { INCREMENT } from '../actionTypes/default'
import { Map } from 'immutable'
export default (state = Map({number: 0}), action = {}) => {
switch (action.type) {
case INCREMENT:
// return new Immutable data structure here
return state.update('number', num => num + 1);
default:
return state;
}
};
The above example is very similar to your original code, except we don't need toObject
from immutableJS, and I have optimized the state update.
What is immutable here? All the state:
state
parameter, is a new immutable Map
;Map.prototype.update()
returns a new immutable instance).This reducer function always returns immutable data, which is great. This is how immutability is implemented in case of reducers: their return values should be immutable.
In you case here, INCREASE_NUMBER
is just a function, so calling toObject
on it makes no sense.
From what I understand, toObject
is a function that can be called on immutable objects to convert them to JS objects. However, there also is merge
function that's used to extend a Map
, and the state value seems to be a Map
, not a JS object, so why do you want to use toObject
anywhere in here?
Just drop that toObject
line.
If the intent was to make the reducer return a JS object instead of a Map
, you'd have to put it inside the function in the return
statement. However, taking a Map
and returning an object seems like a wrong approach to reducers. The state that goes in and out should be the same shape.