Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: why does the init action @@redux/INIT is being twice? #382

Closed
happypoulp opened this issue Jul 31, 2015 · 8 comments
Closed

Question: why does the init action @@redux/INIT is being twice? #382

happypoulp opened this issue Jul 31, 2015 · 8 comments
Labels

Comments

@happypoulp
Copy link

Hi,

I am using redux 1.0.0-rc.

I am sure this does not add any overhead to the redux initialization but I'd like to understand what is the intent behind the fact that the action @@redux/INIT is sent in both Store.js and in combineReducers.js.

Example:

var userReducer = function (state = {}, action) {
    console.log('userReducer was called with state', state, 'and action', action)
    return state;
}
var itemsReducer = function (state = [], action) {
    console.log('itemsReducer was called with state', state, 'and action', action)
    return state;
}

import { createStore, combineReducers } from 'redux'

var reducer = combineReducers({
    user: userReducer,
    items: itemsReducer
})
// Output:
// userReducer was called with state {} and action { type: '@@redux/INIT' }
// userReducer was called with state {} and action { type: 'a.2.e.i.j.9.e.j.y.v.i' }
// itemsReducer was called with state [] and action { type: '@@redux/INIT' }
// itemsReducer was called with state [] and action { type: 'i.l.j.c.a.4.z.3.3.d.i' }

var store = createStore(reducer)
// Output
// userReducer was called with state {} and action { type: '@@redux/INIT' }
// itemsReducer was called with state [] and action { type: '@@redux/INIT' }

Thanks!

@gaearon
Copy link
Contributor

gaearon commented Jul 31, 2015

The first invocation is combineReducers trying to test your reducer for bad patterns. Doing this ASAP helps us have nicer error messages.

The next time you get INIT is when it's actually initialized.

@happypoulp
Copy link
Author

I thought indeed that the random action type was here to perform a reducer sanity check but I didn't knew that the init action was used for a similar purpose in combineReducers. Makes sense now.

Thanks @gaearon !

@topgun743
Copy link

I am sort of having problem with this.

I am using following reducer stuff for managing my state:

/**
 * Gets both local Browser storage and persisted items from Server.
 */
const getActiveNotificationsForUser = () => {
    let localitems = getNotificationsFromBrowserStorage();
    let persistedItems = getServerPersistedNotifications();  //This makes an Ajax call to server

    return [
        ...localitems,
        ...persistedItems 
    ];
};

  const notifications = (state = getActiveNotificationsForUser(), action) => {
         switch (action.type) {
              case AppConstants.NEW_NOTIFICATIONS:
                   // code goes here
              default:
                   return state;
        }
   });

As you can see that getActiveNotificationsForUser function makes an Ajax call to Server, so this @@redux/INIT thing is causing my Ajax to fire thrice.

I have done a workaround however:

const _INIT_ACTION_TYPE = "@@redux/INIT";
let _init_action_count = 0;
const notifications = (state = [], action) => {

      if (action.type === _INIT_ACTION_TYPE) {
          _init_action_count++;

       if (_init_action_count > 1)
           state = getActiveNotificationsForUser();
    }

     switch (action.type) {
              case AppConstants.NEW_NOTIFICATIONS:
                   // code goes here
              default:
                   return state;
       }
}

My question to @gaearon : Is this approach appropriate ?

@gaearon
Copy link
Contributor

gaearon commented Feb 19, 2016

No, this is not how AJAX is Redux apps should work. Reducers should be pure and not cause side effects. You are doing an AJAX call from reducer, which is a side effect. I would suggest you to re-read the docs at http://redux.js.org/ and take a look at examples/async in this repo.

@topgun743
Copy link

Good point.

@ihor
Copy link

ihor commented Feb 16, 2017

I'm new to React/Redux and not sure if I'm not doing something wrong. But I'm having a component making an AJAX call on componentWillMount to fetch data from the server to render.

And the problem is that often second @@INIT is dispatched after I receive the response from the server. It comes with an empty (initial) state which is passed to the component props and I receive a blank screen as the result.

Please see this log produced by the reducer:

screen shot 2017-02-16 at 14 40 41

Am I doing something wrong? How can I solve this issue? Thanks!

@timdorr
Copy link
Member

timdorr commented Feb 16, 2017

@ihor I would ask that kind of thing over on Stack Overflow. Not many people are going to see a comment from nearly one year old issue :)

@ihor
Copy link

ihor commented Feb 16, 2017

That's a good suggestion @timdorr. In case Google brings some else with a similar problem to this thread I posted a StackOverflow question here.

@reduxjs reduxjs deleted a comment from nbmhoang Jan 22, 2021
@reduxjs reduxjs locked as resolved and limited conversation to collaborators Jan 22, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

5 participants