I am currently working on a new project, so I decided to implement React but with server side rendering. I use express as router between pages, so when you access to the home page, the entry point is something like this:
const router = require('express').Router();
const { render, fetchUsers } = require('./controller');
router.use('/', fetchUsers, render);
module.exports = router;
So when you acces the home page, this would get all the users and then it will render the component, in order to render the component I do the following:
const render = (req, res) => {
const extraProps = {
users: res.locals.users.data,
}
return renderView(View, extraProps)(req, res);
}
the fetchUsers method sets res.locals.users with an api response. My renderView do something like this:
const renderView = (Component, props = {}) => (req, res) => {
const content = renderToString(
<LayoutWrapper state={props}>
<Component {...props} />
</LayoutWrapper>
);
res.send(content);
};
My LayoutWrapper is a React Component that replace the html template:
const React = require('React');
const serialize = require('serialize-javascript');
const LayoutWrapper = ({ children, state }) => (
<html>
<head></head>
<body>
<div id={'app-root'}>
{children}
</div>
</body>
<script>
{`window.INITIAL_STATE = ${serialize(state, { isJSON: true })}`}
</script>
<script src={`home.js`} />
</html>
)
module.exports = LayoutWrapper;
The script that sets window.INITAL_STATE = props; is used on the client side to get the props that were fetch. But the problem is the way that the renderToString process the component. The console.log output is the following:
<html data-reactroot="">
<head></head>
<body>
<div id="app-root">
<div>I'm the Home component</div><button>Press me!</button>
<ul>
<li>Leanne Graham</li>
<li>Ervin Howell</li>
<li>Clementine Bauch</li>
<li>Patricia Lebsack</li>
<li>Chelsey Dietrich</li>
</ul>
</div>
</body>
<script>
window.INITIAL_STATE = { & quot;users & quot;: [{ & quot;id & quot;: 1,
& quot;name & quot;: & quot;Leanne Graham & quot;
}, { & quot;id & quot;: 2,
& quot;name & quot;: & quot;Ervin Howell & quot;
}, { & quot;id & quot;: 3,
& quot;name & quot;: & quot;Clementine Bauch & quot;
}, { & quot;id & quot;: 4,
& quot;name & quot;: & quot;Patricia
Lebsack & quot;
}, { & quot;id & quot;: 5,
& quot;name & quot;: & quot;Chelsey Dietrich & quot;
}]
}
</script>
<script src="home.js"></script>
</html>
Is there any way to do this without having to declare the html template as a simple string, and instead having a Wrapper component that sets the html code structure?