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

contextType apparently not working in dev mode server side rendering #14793

Closed
EthanRutherford opened this issue Feb 8, 2019 · 8 comments
Closed

Comments

@EthanRutherford
Copy link

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
Crash during server render due to this.context being undefined. Bug only happens in SSR, and only in dev mode react. Issue appears neither in browser renders, nor in production mode server renders.

note: Using https://reactjs.net/ for c# server-side rendering, with bundled-in version of react disabled (so using the same version of react as the client bundle)

(simplified) application structure

// root component
const {Provider, Consumer} = createContext({});
const Root = props => return <Provider value={props.notNull}>{props.children}</Provider>;

// consumer
class ConsumingComponent extends Component {
  static contextType = Consumer;

  render() {
    if (this.context.someValue) return null;
    return <div/>;
  }
}

// render tree
<Root>...<ConsumingComponent/>...</Root>

// output of server render
JsRuntimeException: TypeError: unable to get property 'someValue' of undefined or null reference.

What is the expected behavior?
this.context in the consuming component should be the value passed to the Provider, and not undefined.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

The bug, as best as I can pin down, appeared in 16.6.3. The code works in 16.6..1, and 16.6.2 is listed as a broken release in the changelog.

@hamlim
Copy link
Contributor

hamlim commented Feb 8, 2019

The issue could be that you are providing the Consumer as the static contextType value. Instead static contextType should be assigned the entire context object:

const context = createContext({});
const {Provider, Consumer} = context;
class ConsumingComponent extends Component {
  static contextType = context; // assign `context` here, not `Consumer`

  render() {
    if (this.context.someValue) return null;
    return <div/>;
  }
}

I think there should be a warning for this, however it may only be for the client side renderer (i.e. it might not warn within react-dom/server, if that is what the c# rendering implementation uses).

@gaearon
Copy link
Collaborator

gaearon commented Feb 8, 2019

@hamlim Good catch.

@EthanRutherford
Copy link
Author

That's a bit unfortunate then, I didn't expect I'd have to expose the entire context object. In my setup, I expose the context consumer for other components to use, but Root in the example is the only thing which should ever use the provider.

This still seems like a bug to me, I'd expect consumers of a context to use context.Consumer, even if they are using contextType.

@gaearon
Copy link
Collaborator

gaearon commented Feb 8, 2019

This is intentionally unsupported but the warning seems necessary.

@EthanRutherford
Copy link
Author

So is the only solution to break encapsulation, and export the whole context object then? Is there any other alternative?

@aweary
Copy link
Contributor

aweary commented Feb 11, 2019

@gaearon we currently warn only when passing Context.Provider, should we extend that to also warn for Context.Consumer?

@gaearon
Copy link
Collaborator

gaearon commented Feb 12, 2019

So is the only solution to break encapsulation, and export the whole context object then?

In longer term we might change the API a little bit for now, yes.

@EthanRutherford
Copy link
Author

Ok, thanks for the information.

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

No branches or pull requests

4 participants