Simple base class for truly SSR-capable React components
Go to file
Vitaliy Filippov 57cd762262 Get key from item (not props), do not update state if there is no change 2021-09-21 18:24:16 +03:00 Initial commit 2021-08-08 00:51:04 +03:00
SSRComponent.js Faster and more correct variant which does not recreate full DOM tree on every run 2021-08-08 12:22:51 +03:00
renderToHtml.js Remove extra spaces in the style attribute to better match React 2021-09-19 20:37:56 +03:00
virtualRender.js Get key from item (not props), do not update state if there is no change 2021-09-21 18:24:16 +03:00

This is a simple base component class for true server-side rendering with emulation of server interaction.

It is intended for use with class components and without any external state management libraries like Redux. Basically it's intended for pure setState()-based code.


  • Write code in such a way that it still works if DOM is not available
  • Make your components inherit from SSRComponent:
    • Use doRender instead of render
    • Use init instead of constructor
    • Everything else stays the same
    • You can additionally override serializeState and unserializeState if your state isn't directly JSON-serializable
  • Implement SSR:
    • Declare store = {}
    • Render your component using react-test-renderer with store={store} in props
    • Make sure your code tracks all fetch() requests (server interactions) during render
    • And of course mock fetch() (or analogue) to use internal server-side calls
    • Wait until all fetch() requests complete
    • Re-render until the component stops issuing additional requests
    • Render HTML using renderToHtml(testRenderer.toJSON())
    • Serialize state using JSON.stringify(SSRComponent.serializeStore(store))
  • Hydrate the rendered HTML in your frontend code:
    • Call ReactDOM.hydrate() instead of ReactDOM.render()
    • Pass serialized state from the last step of SSR to your top-level SSRComponent


Simpler (but less compatible) alternative to react-test-renderer.


import virtualRender from 'virtualRender.js';

const options = {};
let html = virtualRender(<Component {...props}>, options);
while (options.shouldUpdate)
    html = virtualRender(<Component {...props}>, options);

Author and License

Author: Vitaliy Filippov, 2021+

License: Dual-license MPL 1.1+ or GNU LGPL 3.0+ (file-level copyleft)