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

Only render node on Client Side. #4374

Closed
tnulc opened this issue Jul 14, 2015 · 5 comments
Closed

Only render node on Client Side. #4374

tnulc opened this issue Jul 14, 2015 · 5 comments

Comments

@tnulc
Copy link

tnulc commented Jul 14, 2015

We're using isomorphic rendering in our app, however we want some items to not be present if Javascript is disabled. In our render method we're doing the following:

render: function() {
  if(typeof window === 'undefined') {
    return null;
  }
  return <span>Hello World</span>;
}

It works as expected, however we get the warning:

Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:

The way to make this go away is to store the check like this:

componentDidMount: function() {
  this.setState({ isBrowser: typeof window !== 'undefined' });
},
render: function() {
   if(!this.state.isBrowser) {
    return null;
  }
  return <span>Hello World</span>;
}

However, it doesn't seem like this is the "right" place for this to live, maybe I'm wrong. I could also use this.isMounted(), however as this is deprecated, it doesn't make much sense to use it.

Does anyone else have any thoughts on the best way to approach this?

@waldreiter
Copy link
Contributor

One idea is to render on the client twice:

React.render(<MyApp isFirstRender={true}/>, container);
React.render(<MyApp isFirstRender={false}/>, container);

@syranide
Copy link
Contributor

Related #1979, basically what @cody said.

@solomonhawk
Copy link

Would it be sufficient to add a renderSource="server" to the Router when rendering server-side and pass it down as a prop to any components that need to know about it? On the client you would set this to "client". Then in your component you can use this.props.renderSource and avoid the double render on the client.

Netflix does this.

netflix-rendersource

@dantman
Copy link
Contributor

dantman commented Jul 27, 2015

That would quickly get messy if deep components need it.

Parent contexts would work. Though #4218 might make that a problem. And the jury is still out on #2517.

@jimfb
Copy link
Contributor

jimfb commented Feb 11, 2016

I think the official recommendation at this point would be to use context for things like this. That also allows you to simulate a server-side render for initial mount on the client side, which is a pretty handy trick/feature to make the nodes/checksums align.

@jimfb jimfb closed this as completed Feb 11, 2016
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

6 participants