Answer a question

Upgrading meteor (from 1.4 to 1.7) and react (from 15.3.2 to 16.8.6).

"react-redux": "^4.4.10"
"redux": "3.5.2"

I found my codes were unable to update/store using Store.dispatch(), the Store just not updated.

My ACTIONS file as below:

actions/config.js

...
export default {
  load({Meteor, Store}) {
    return new Promise((resolve, reject) => {
      Meteor.call('variables.load', null, (err, data) => {
        if (err) {
          reject({_error: err.reason });
          return;
        }

console.log("************ Store (A) = "+JSON.stringify(Store.getState()))
        Store.dispatch({
          type: LOAD_CONFIG,
          data
        });

        resolve();
console.log("************ Store (B) = "+JSON.stringify(Store.getState()))
      });
    });
  },
...

Both the console.log() were having the following:

Store (A) = {"router":{"locationBeforeTransitions":{"pathname":"/settings/config","search":"","hash":"","action":"PUSH","key":"zif4ls","basename":"/crm","query":{}}},"form":{"config":{"syncErrors":{"reportLimit":"Required"}}},"loadingBar":{}}

Store (B) = {"router":{"locationBeforeTransitions":{"pathname":"/settings/config","search":"","hash":"","action":"PUSH","key":"zif4ls","basename":"/crm","query":{}}},"form":{"config":{"syncErrors":{"reportLimit":"Required"}}},"loadingBar":{}}

Which I do expect it will have something like "reportLimit":6 , which was confirmed to have loaded into the data variable. Instead, I was getting the following error in browser console:

Uncaught TypeError: Cannot read property 'data' of undefined

Is there anything wrong/breaking changes you could think of? As these codes had been working before the upgrade.


EDIT:

I've further narrowed down the problem. It may seems to be my Routes is not calling the Reducer.

I've since change the code in my Routes to remove the need to use require.ensure .

routes.jsx (prior)

 {
     path: 'config',
     getComponent(nextState, cb) {
         require.ensure([], (require) => {
           Store.injectReducer('config', require('./reducers').config)
           cb(null, require('./containers/config.js'))
         }, 'config')
     }
 },

routes.jsx (latest, to get rid of require.ensure)

 {
      path: 'config',
      getComponent(nextState, cb) {
      import('./containers/config.js')
      .then(mod => {Store.injectReducer('config', require('./reducers').config); 
      cb(null, mod);});
      }
 },

Then I notice that in the reducer:

reducer/config.js

// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
    [LOAD_CONFIG]: (state, action) => ({
      ...state,
      data: action.data
    })
};

// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
    data: null
};

export default function configReducer(state = initialState, action) {
console.log("************ Reducer")
    const handler = ACTION_HANDLERS[action.type];

    return handler ? handler(state, action) : state;
}

As per logged, function configReducer doesn't seem to have been called elsewhere.

Answers

After much trial-and-error, confirmed the problem is with the routing part, final changes:

routes.jsx (final)

{
    path: 'config',
    getComponent(nextState, cb) {
        import('./containers/config').then(mod => {
            Store.injectReducer('config', require('./reducers/config').default);
            cb(null, mod.default);
        });
    }
}

Key points: 1) This is how the to migrate from require.ensure (used by webpack) to without relying on webpack (which was my case as am fully using Meteor Atmosphere to run) 2) mod and require(...).xxx had changed to mod.default and require(...).default if reducer function is exported as export default, otherwise said reducer will not be called.

Really took me weeks to figure this out!

Logo

React社区为您提供最前沿的新闻资讯和知识内容

更多推荐