In the new docs (#140) we should clarify that any actions prefixed with @@ are _not_ meant to be handled. For example, you should never try to handle @@INIT. We might enforce that by slightly randomizing names (e.g. @@INIT_2hj3jh34).
Handling @@INIT manually will break hot reloading. It is invoked at every hot reload, so if you do your initial data transformation there, it won't work the second time.
I've seen people using @@INIT to hydrate the plain objects received from the server into the Immutable state. Instead of handling @@INIT, you need to consider one of two options:
state is a plain object and use fromJS before handling the action.function myReducer(state = {}, action) {
if (!isImmutable(state)) { // some kind of typeof check here?
state = Immutable.fromJS(state);
}
...
}
It is easy to abstract this away with a createImmutableReducer function like this:
export default function createImmutableReducer(initialState, handlers) {
return (state = initialState, action) => {
if (!isImmutable(state)) {
// Hydrate server plain object state
state = Immutable.fromJS(state);
}
const handler = handlers[action.type];
if (handler) {
state = handler(state, action);
}
if (!isImmutable(state)) {
throw new Error('Reducers must return Immutable objects.');
}
return state;
};
}
It can then be used for creating reducers from action constant -> handler map.
@gaearon What is "@@"? I'm assuming it's ES6, perhaps related to symbols, but google doesn't like special characters so it ungoogleable :(
@hummlas it's random to tell it's an internal :) @ooflorent proposed it as far as I remember
Ah, I see, like old-school underscore prefixes, e.g. var _privateValue = "Private";? :)
It seem to be used in official spec-stuff as well, like iterables
"In order to be iterable, an object must implement the @@iterator method, meaning that the object (or one of the objects up its prototype chain) must have a property with a Symbol.iterator key"
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols
This confuses me a bit as you're supposed to implement an @@iterator method, which, to me, seems to be at odds with @@ meaning "internal"?
Feel free to suggest better prefix. I have no idea what to choose to discourage people from actually handling them, but keep it readable. Maybe prefix with an emoji..
I'd use something like @@redux/INIT, or @@redux/__INIT to stress that it's private. This would be similar to, e.g. @@transducer/step in that there is a namespace at the top.
Oh, I like the namespace thing!
REDUX:INIT?
I like the @@ because of possible familiarity (it is already used for iterators and transducers in a similar manner). Capitalization is to look like an action constant. Underscores as a hint for internals. Making it look frightening as an additional hint :) It would also be extensible for possible non-privately namespaced constants.
But any naming scheme should be fine, provided that it is unlikely to clash with user's action constants.
Could symbols be used for methods and variables that aren't supposed to be handled by the consumer?
But maybe that would break the hot reloading as well? But then if that's the case that could be solved by exposing a collection of symbols, that way the methods/variables wouldn't be accessible without retrieving there corresponding symbol first?
I might be speaking out of ignorance here though as I have no experience with hot reloading or symbols (yet), so I defer to your superior knowledge in this area :)
Btw, I must say that reading the issues for Redux is extremely educational and enjoyable, it's so cool being able to follow along in the creation of a new library, especially the back and fourth between @gaearon and @acdlite when brainstoring new ideas. Kudos! :)
Symbols might be problematic for use from third-party libraries: they would be required to import redux, which may lead to more coupling.
Could symbols be used for methods and variables that aren't supposed to be handled by the consumer?
That's what I wanted at first, but we decided against them because it feels silly to drag a Symbol polyfill (16% of the lib size) just for that.
Maybe we should namespace the init type, like the transducer protocol does?
export const INIT = '@@redux/init';
Oh haha that was already suggested. Well I like that idea :D
Fixed by #186.
Just for info, I arrived here precisely because I was feeling it would be bad to react to this action, so I think the name makes it actually pretty clear it should not be used. If you really want to make it clear that it should not be used I think the best name would be "@@INIT_action_do_not_react_to_this_action_check_issue_186_instead" or something alike...
So I am in a situation where I would like to call a saga on startup. Is there any better way then listening to @@INIT ?
@MoeSattler const store = createStore(...); store.dispatch(...)
So whats the purpose to having init action that i cannot use to init values. Also it is double confusing when someone uses redux dev tools where it is just @@INIT and when using compose on production build he will learn that its not working after wasting some time on debugging and then finding this thread...
And to fix my issues I need to send similar action just after creating store...
const defaultState = {
iDontWantDeepState: true,
}
const reducer = (state = {}, action) => {
switch (action.type) {
case MY_INITIALIZE_BECAUSE_WHY_HAVE_STANDARDS:
return { ...defaultState, ...state };
}
}
Most helpful comment
Oh, I like the namespace thing!