markfinger/python-react

Is it possible to use Server Side Rendering for components that you want to pass children to?

Anima-t3d opened this issue · 5 comments

As I understand from the docs you can only pass the absolute url of a jsx file and pass props. Would it also be possible to pass child components to the server side renderer? Or would a somewhat workaround be to create another jsx file that has these child components in it and pass props?

You could implement something like that with React components if you use the render method to handle the instantiation of - and branching between - the child components, but it'll probably involve jumping through a number of hoops and seems a bit hacky.

An alternative might be to re-implement the render server's js file with your own. If you're interested, it's pretty succinct and should be easy to hack on

I've linked this question from the README. https://github.com/markfinger/python-react/blob/master/README.md#how-do-i-pass-child-components-to-the-root-component

Everyone should feel free to continue the discussion, if so inclined.

I was able to get this to work, but would be open to any suggestions if someone knows a better way. I modified the render server's js file from:

app.post('/render', function(req, res) {
	reactRender(req.body, function(err, markup) {

to

app.post('/render', function(req, res) {
        var component = require(req.body.path);
	reactRender({
             props: { children: component.default(JSON.parse(req.body.serializedProps)) },
             toStaticMarkup: false,
             path: '<path_to_my_main>',
  }, function(err, markup) {

I came up with this after looking at the code inside react-render, which is a bit more defensive (I'm not using any of the custom config options, so ymmv with this sample).

@ryapapap that seems pretty reasonable.

The primary benefits of react-render is require caching (reduce IO) and some compatibility for different React versions. There's no massive benefit to using it, other than excising some boilerplate from the render server's script.

If you want more granular control of the render process, but still use the req/res conventions + handling in python-react, you could always just remove the reactRender call and replace it with your own React.renderToString call. You'll probably want to replicate some of the React Factory stuff (I think it's a one-liner and should be easy to find in react-render's code or React's docs) as I think that avoids re-running some of React's init code. Once you've got a reference to the component factory, it should be trivial to pass in any child components you like.

Either way, @ryapapap's code above should work well enough for most purposes.

That makes a lot of sense, thanks for the info!