Redux: error when use redux @connect and this.context.router

Created on 20 Aug 2015  路  15Comments  路  Source: reduxjs/redux

I want to use it like this:


@connect(state => state)
class MessageComposer extends Component {

  componentWillMount() {
    // send login action
    const { dispatch } = this.props;
    dispatch(checkLogin(this.context.router));
  }

  render() {
    return (
      <div>
        <h1>MessageComposer</h1>
        <Link to='/login' >GO!</Link>
      </div>
    );
  }
}

MessageComposer.contextTypes = {
  router: React.PropTypes.object,
};

export default MessageComposer;

but it would give me some error like this

Uncaught Error: Invariant Violation: Could not find "store" in either the context or props of "Connect(MessageComposer)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(MessageComposer)".

after I remove the decorator and change it like this

export default connect(state => state)(MessageComposer);

it would work

if i remove router context declare,it would work too

ps:

    "react-router": "^1.0.0-beta3",
    "react-redux": "^0.8.0",
    "redux": "^1.0.1",
question

Most helpful comment

My advice today is don鈥檛 use decorators at all. They are too easy to break with Babel 6, and they are not even an official feature in it. For example, specifying plugins in a different order can cause decorators to work incorrectly with static properties in Babel 6, which is likely the issue you are experiencing.

Until decorators are officially supported by Babel and the plugin ordering issues are solved, just avoid them:

class Root extends Component {
    static contextTypes = {
        router: React.PropTypes.object,
    }        
}

export default connect(state => state)(Root)

All 15 comments

Is that component wrapped in a <Provider> component?

yes, if I remove contextTypes,it would work, and dispatch the action

If you _remove_ contextTypes? That's not supposed to work that way. React only passes context if you request it via contextTypes.

But that doesn't address what I asked. Are you wrapping this in a <Provider> component higher up?

yes, I wrap <MessageComposer>in a <Route>,<Route> is in<Router>
and I wrap the <Router> in <Provider>

If I remove contextTypes, this.context.router wouldn't work,but @connect would work,and I can get dispatch from this.props

You can declare contextTypes as static class prop like this:

class MessageComposer extends Component {
  static contextTypes = {
    router: React.PropTypes.object,
  }
  //...
}

Your component's own contextTypes won't conflict with connect(). It creates a higher-order component, so it has it's own context and therefore it's own local contextTypes.

@miafmira thanks

@timdorr that's the point I want to figure out,if I use

export default connect(state => state)(MessageComposer);

it's ok

The decorator syntax is essentially desugars to the same thing. Are you using babel with at least stage 1 enabled?

after I change code to syntax @miafmira suggested before

class MessageComposer extends Component {
  static contextTypes = {
    router: React.PropTypes.object,
  }
  //...
}

it would work

this syntax

MessageComposer.contextTypes = {
  router: React.PropTypes.object,
};

wouldn't work

Yes, that is correct. The way statics desugar is slightly different than just setting a property on the class.

Either use ES7 proposal syntax both for properties and decorators (dangerous: subject to change), or just use ES6.

@connect(...)
class Stuff {} 

// WON'T WORK
Stuff.contextTypes = {
  router: React.PropTypes.object,
};

does not work because you're assigning contextTypes to the wrapped component returned by connect. It's like doing this:

class Stuff {}
Stuff = connect(...)(Stuff);

// WON'T WORK
Stuff.contextTypes = {
  router: React.PropTypes.object,
};

i'm getting the same issue:

@connect(state => state)
export default class Root extends Component {
    static contextTypes = {
        router: React.PropTypes.object,
    }        
}

if i remove contextTypes it works fine...
@gaearon you mentioned using ES7 for both, am i doing it the wrong way?

My advice today is don鈥檛 use decorators at all. They are too easy to break with Babel 6, and they are not even an official feature in it. For example, specifying plugins in a different order can cause decorators to work incorrectly with static properties in Babel 6, which is likely the issue you are experiencing.

Until decorators are officially supported by Babel and the plugin ordering issues are solved, just avoid them:

class Root extends Component {
    static contextTypes = {
        router: React.PropTypes.object,
    }        
}

export default connect(state => state)(Root)

thank you for the advice Dan

Was this page helpful?
0 / 5 - 0 ratings

Related issues

benoneal picture benoneal  路  3Comments

elado picture elado  路  3Comments

olalonde picture olalonde  路  3Comments

rui-ktei picture rui-ktei  路  3Comments

ilearnio picture ilearnio  路  3Comments