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

React's getChildContext doesn't set child context properly? #2

Closed
TimFletcher opened this issue Jul 7, 2015 · 8 comments
Closed

React's getChildContext doesn't set child context properly? #2

TimFletcher opened this issue Jul 7, 2015 · 8 comments

Comments

@TimFletcher
Copy link
Contributor

If I have a simple root component in React

AppLayout = React.createClass({

  childContextTypes: {
    muiTheme: React.PropTypes.object
  },

  getChildContext: function() {
    return {
      muiTheme: ThemeManager.getCurrentTheme()
    };
  },

  render() {
    return (
      <div>
        { this.props.content }
      </div>
    )
  }
});

And a FlowRouter / ReactLayout setup like this

FlowRouter.route('/register', {
  name: 'register',
  action: function(params) {
    ReactLayout.render(AppLayout, { content: <AuthRegisterPage /> });
  }
});

Then within the render() method of AuthRegisterPage, this.context is undefined. However, if I don't use { this.props.content } and simply have <AuthRegisterPage /> within the AppLayout component then this.context returns {muiTheme: someobject} as I'd expect.

I'm not a react expert by any means. Am I missing anything?

@TimFletcher TimFletcher changed the title React's getChildContext doesn't set context properly? React's getChildContext doesn't set child context properly? Jul 7, 2015
@TimFletcher
Copy link
Contributor Author

Could be related to this (and thus not a FlowLayout issue) — http://stackoverflow.com/questions/30368433/react-context-doesnt-transfer-when-using-a-component-as-prop

@arunoda
Copy link
Contributor

arunoda commented Jul 8, 2015

I think it makes sense since we render it outside AppLayout. May be we can render it inside AppLayout. Let me give it a try.

@arunoda
Copy link
Contributor

arunoda commented Jul 8, 2015

Yeah! It worked. Here's how to get this to work. So, basically, you need to render the component inside the layout. So, we can pass a function as the content. So, here's our layout:

AppLayout = React.createClass({

  childContextTypes: {
    muiTheme: React.PropTypes.string
  },

  getChildContext: function() {
    return {
      muiTheme: "blue-theme"
    };
  },

  render() {
    return (
      <div>
        { this.props.content() }
      </div>
    )
  }
});

Here's our Login component:

LoginPage = React.createClass({
  contextTypes: {
    muiTheme: React.PropTypes.string
  },
  render() {
    return <div>
      <h1> Login Page { this.context.muiTheme } </h1>
    </div>
  }
});

Here's the router:

FlowRouter.route('/', {
  name: 'register',
  action: function(params) {
    ReactLayout.render(AppLayout, {
      content() { return <LoginPage /> }
    });
  }
});

@TimFletcher
Copy link
Contributor Author

Ahhh, yes! Works great for me too. Thanks, Arunoda!

@arunoda
Copy link
Contributor

arunoda commented Jul 8, 2015

BTW: Would you mind sending a PR to the README mentioning this issue and referencing to here.

@TimFletcher
Copy link
Contributor Author

Absolutely.

@mbrookes
Copy link

This might be a "Duh Bob" moment, but I was also able to use this method (passing a function as the content) to propagate an event up to the layout from a button in a sub-component, and affect props on another component contained in the layout. (Specifically to set button state in a toolbar that is present in all views, so lives in the layout).

In Layout.jsx:

{this.props.content((result) => {this._someEventHandler(result)})}

And an associated function to set state or whatever: _someEventHandler(result) {...}

In routes.jsx:

FlowRouter.route('/', {
  action() {
    ReactLayout.render(MainLayout, { content(_myCallback) { return (
      <Component callback={(result) => {_myCallback(result)}}/>
    )}});
  }
});

In Component.jsx:

<SubComponent onTouchTap = {() => {this.props.callback(objectToBubbleUp)}} />

Is this the right way to go about it? It's a bit cumbersome, but it works...

@rulatir
Copy link

rulatir commented Mar 31, 2016

I just noticed something that might be unrelated but it might be the root cause of this problem as well. WHEN your app throws a RSOD on startup and that is the reason why you want to debug, then it might have happened that you have previously clicked on a stack frame on the RSOD. If you have, then RN communicated with whatever daemon is running on your PC that the command npm start in your app's directory starts, and that daemon launched your $EDITOR to show the file and line. If the editor is something like nano or mcedit that doesn't detach from terminal, then the daemon is blocked and stops responding, which is why RN can no longer speak to the debugger. The workaround (for linux) is to run npm start with $EDITOR=/bin/true.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants