is it possible to trigger render only in client side, not on the server
i'm trying to use this example (google map)
http://tomchentw.github.io/react-google-maps/async/
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.
my goal is to load the google map library and then render the map on the client side only
Any help?
How about partial render on client side?
componentDidMount() {
if (__CLIENT__) {
// initialize google map here
}
}
@micooz i tried very similar to your answer but get warning
import {default as canUseDOM} from 'can-use-dom';
render() {
if (!canUseDom) {
return (<div/>);
}
return (
<ScriptjsLoader ... )
}
but i get 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:
I would recommend using __CLIENT__. Best to try and avoid those switches when possible, and instead use something like componentDidMount
@quicksnap i get this waring when i used __CLIENT__ with componentDidMount
setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.
@NourSammour I don't think you need __CLIENT__ inside componentDidMount 'cause componentDidMount is only called on the client. Try to do it like so:
...
state = {
scriptjsLoaderEnabled: false
};
componentDidMount() {
// initialize the lib here?
// ...
this.setState({scriptjsLoaderEnabled: true})
}
render() {
if (!this.state.scriptjsLoaderEnabled) {
return (<div/>);
}
return (
<ScriptjsLoader ... )
}
@Dattaya Thanks, it's work perfectly :+1:
the issue solved
Hi, im trying to get this working, I have the same problem described above. Ive tried the solution with componentDidMount but the error persist. Maybe Im missing something.
Ive made a repository with the initial boilerplate and only adding the map component called AsyncMap:
https://github.com/OkuraSt/example-maps
The Map component is added on Home.js.
Could someone give me a hint, Thanks for your time.
@OkuraSt try this
export default class MyMap extends Component {
state = {
inBrowser: false
};
componentDidMount() {
this.setState({ inBrowser: true });
}
render() {
if (this.state.inBrowser) {
res = this.renderMap();
} else {
res = <span>Loading</span>;
}
return res;
}
}
@NourSammour Thanks man,
Ive tried your suggestion, my component now looks like this:
export default class AsyncMap extends Component {
state = {
markers: [{
position: {
lat: 25.0112183,
lng: 121.52067570000001,
},
key: 'Taiwan',
defaultAnimation: 2
}],
inBrowser: false
}
componentDidMount() {
// initialize the lib here?
// ...
this.setState({inBrowser: true});
}
renderNewBehavior() {...}
render() {
let res = null;
if (this.state.inBrowser) {
res = this.renderNewBehavior();
} else {
res = <span>Loading</span>;
}
return res;
}
}

I don't know if I'm missing something very easy, but the error is persisting.
I really appreciate your time, thanks
I could get it working by setting the height and width of the container element to a specific number of pixels. Now Im tryng to resize it to 100% height. I appreciate any help. Thanks
Hey, guys, @OkuraSt, @NourSammour, @Dattaya! Does anybody see the problem when you use __CLIENT__ or componentDidMount for detecting client-side and rendering specific code the console show error about difference in server-side and client-side markup?
For example:
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:
(client) hvf5a2k1s.2.0.1.0"><div class="form-row
(server) hvf5a2k1s.2.0.1.0"></div></div><div data
As you can see, on the server side my component is simple </div></div> however on the client side it has real content starting with <div class="form-row.
Does this case make the React to re-render the whole DOM-tree and all server side rendering become a unuseful stuff or it just tries to re-render only this specific component?
Thanks a lot.
Hi, @Znack. This shouldn't be the case, unless you use __CLIENT__ inside the render method. Initially the server and the client return the same virtual dom, then when component has been mounted on the client side, in componentDidMount we set a new state and of course it rerenders the component.
@Dattaya, yep, actually I used __CLIENT__ inside the render method, so when I implemented your suggestion with setting new state in componentDidMount everything become working. Thank you very much.
But I have met one eslint issue: react/no-did-mount-set-state rule does not allow call setState within componentDidMount, I suppose it is some kind of a bad practice, but I have disabled eslint for this particular line. I hope it will not be a cause of some unpredicted strange problems in the future ;)
@Dattaya You can make another function and eslint won't trigger
componentDidMount() {
setClientSideState();
}
setClientSideState() {
this.setState({client: true});
}
Thank you, @gabriel-miranda, good to know.
@Znack, here's some reasoning behind that rule (no-did-mount-set-state)--https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-did-mount-set-state.md; not that I completely understand it, but for this particular case I think it's legit to use setState.
Thank you, @gabriel-miranda, @Dattaya, I also suppose it is not the big deal to use setState for this particular case, so I have used comment eslint-disable-line and now everything is great.
Most helpful comment
@OkuraSt try this