React-redux: 5.0.0 key "storeSubscription" is not defined in childContextTypes.

Created on 14 Dec 2016  路  7Comments  路  Source: reduxjs/react-redux

Tried the new version against react-native 0.38.1 (react 15.4.0-rc.4), but no joy

screen shot 2016-12-14 at 11 57 58

Most helpful comment

Ah. I think you're overwriting Connect's childContextTypes with your own. Try changing NavigationContainer.childContextTypes = { ... } to NavigationContainer.WrappedComponent.childContextTypes = { ... }

All 7 comments

We're gonna need more details. Connect definitely defines childContextTypes.

Ok, what kind of details do you need? I can give you some of my code setup:

I noticed that NavigationContainer defines a childContextTypes of its own. Perhaps it overwrites the react-redux setting instead of merging it?

index.ios.js

import './app/dev/Reactotron';
import { AppRegistry } from 'react-native';
import Root from './app/App';

AppRegistry.registerComponent('Ology', () => Root);

App.js

import React from 'react';
import { Provider } from 'react-redux';
import { MenuContext } from 'react-native-popup-menu';
import UIContainer from './modules/navigation/components/UIContainer';
import routez from './resources/routez';

import { styles } from './MSA';

import configureStore from './store/configureStore';
const store = configureStore();

export default class Root extends React.Component {

    render() {
        return (
      <Provider store={store}>
          <MenuContext style={styles.stretch}>
              <UIContainer
                  routes = {routez}
              />
          </MenuContext>
      </Provider>
        );
    }
}

configureStore.js

import { createStore, applyMiddleware, compose } from 'redux';
import thunkMiddleware from 'redux-thunk';
import loggerMiddleware from 'redux-logger';
import rootReducer from './reducers';
import { persistStore, autoRehydrate } from 'redux-persist';

import { middleware as netInfoMiddleware } from '../modules/connection/middleware';

import config from '../config';

const initialState = {};

export default function configureStore() {

    let enhancer;

    if(__DEV__) {

        const Reactotron = require('reactotron-react-native').default;
        const createReactotronEnhancer = require('reactotron-redux');
        const reactotronEnhancer = createReactotronEnhancer(Reactotron);

        enhancer = compose(
      reactotronEnhancer,
      applyMiddleware(
        thunkMiddleware,
        netInfoMiddleware,
        loggerMiddleware(),
      )
    );
    }else{

        enhancer = compose(
      applyMiddleware(
        thunkMiddleware,
        netInfoMiddleware,
      )
    );
    }

    const store = createStore(rootReducer, initialState, enhancer);

    if (module.hot) {
        module.hot.accept('../reducers', () => {
            const nextRootReducer = require('./reducers').default;
            store.replaceReducer(nextRootReducer);
        });
    }

    return store;
}

NavigationContainer

@connect(
    (state) => {
        const { notifications, inboxReducer, progress,  navigation, connection, wsReducer, menu } = state;

        return {
            spinner : progress.spinner,
            navigationState : navigation.navigationState,
            routeRegistryRoutes : navigation.routeRegistry.routes,
            notificationCount : notifications.newNotificationsCount,
            messageCount : inboxReducer.newMessageCount + inboxReducer.newInviteCount,
            connected : connection.connected,
            wsActiveGroups : wsReducer.activeGroups
        };
    },
  (dispatch) => {
      return {
          dispatch,
          navigate : (path, title) => dispatch(doNavigate(path, title)),
          navigateReset : (path, title) => dispatch(doReset(path, title)),
          navigateBack : () => dispatch(doNavigatePop()),
          formActions : bindActionCreators(formActionCreators, dispatch)
      };
  }
)
@autobind
class NavigationContainer extends React.Component {
    [...]
    }

    NavigationContainer.childContextTypes = {
       navigator    : PropTypes.object.isRequired
    };

Ah. I think you're overwriting Connect's childContextTypes with your own. Try changing NavigationContainer.childContextTypes = { ... } to NavigationContainer.WrappedComponent.childContextTypes = { ... }

Thanks. That seems to do the trick. I wonder if this should be documented?

I also noticed that if using the following style, I avoid this issue altogether. It seems more elegant

 class NavigationContainer extends React.Component {
      static childContextTypes = {
         navigator  : PropTypes.object.isRequired
      }

Docs might help, although I wonder how many people would remember that. I think that's part of the downside of decorators. It looks like you're setting a field on one thing, when really you're setting it on another thing. It's a little more obvious when you write it the "traditional" way.

@connect(...)
class NavContainer extends Component { ... }
NavContainer.childContextTypes = { ... }

is equivalent to

class NavContainer extends Component { ... }
const NavContainerConnector = connect(...)(NavContainer)
NavContainerConnector.childContextTypes = { ... }

Well, at least its documented here for posterity. Maybe it will help someone as well. Thx!

If you think there's a good spot in the docs to talk about this, a PR would be welcome.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

psbanka picture psbanka  路  4Comments

nainardev picture nainardev  路  3Comments

a-koka picture a-koka  路  3Comments

julienvincent picture julienvincent  路  4Comments

nmaves picture nmaves  路  3Comments