问题
In my reducer I set initial state by:
const initialState = fromJS({
results: [],
});
However if I try to print results by
initialState.get('results')
I get an immutable Map.
On the other hand if in my reducer (listening to an action) I set the array via
...
case LOAD_SUCCESS:
return state
.set('results', []);
...
the array will be an actual (non-Immutable) array after executing:
state.get('results')
(e.g. in a selector defined via reselect)
Why?
回答1:
From the fromJS
docs:
Deeply converts plain JS objects and arrays to Immutable Maps and Lists.
That said, fromJS({ results: [] })
is equal to Map({ results: List([])})
as soon as you call state.set('results', [])
, you replace List([])
with plain array []
.
This is a classical trap for new starters.
The way I see it is you have to choose to either always use List there, or plain array.
List way:
Initialize: const state = fromJS({results: []})
Reduce: return state.update("results", list => list.clear())
Array way #1:
Initialize: const state = fromJS({results: null})
INIT reduce (dispatched once, to init state) return state.set("results", [])
Reduce: return state.set("results", [1, 2, 3])
Array way #2:
Initialize: const state = Map({results: []})
Reduce: return state.set("results", [1, 2, 3])
I'd recommend to always use Array way #2. It adds more code, as you have to control List
/ Map
for each state's field, but it guarantees you that you get exactly what you want.
In the end it comes something like this:
const initialState = Map({
results: [],
some_field_as_list: List([]),
some_field_as_map: Map([]),
... // etc
});
回答2:
fromJS({ results: [] })
is equal to Map({ results: List([])})
,
Using state.set('results', [])
you replace List([])
with plain []
I found this helpful in this case:
Initialize:
const state = fromJS({results: []})
Reduce:
return state.set('results', List([1,2,3]));
It was better than using plain array because later you can use setIn
function editing the same state
variable:
return state.setIn(['results',state.get("results").size], nextElement);
or
return state.setIn(['results',-1], lastElement);
来源:https://stackoverflow.com/questions/43716784/how-to-set-a-property-as-an-array-i-initial-state