What is the general practice of setting the initial state of the app with isomorphic applications? Without Flux I would simple use something like:
var props = { }; // initial state var html = React.renderToString(MyComponent(props);
Then render that markup via express-handlebars and display via {{{reactMarkup}}
.
On the client-side to set the initial state I would do something like this:
if (typeof window !== 'undefined') { var props = JSON.parse(document.getElementById('props').innerHTML); React.render(MyComponent(props), document.getElementById('reactMarkup')); }
So yes essentially you are setting the state twice, on server and client, however React will compare the differences and in most cases so it won't impact the performance by re-rendering.
How would this principle work when you have actions and stores in the Flux architecture? Inside my component I could do:
getInitialState: function() { return AppStore.getAppState(); }
But now how do I set the initial state in the AppStore from the server? If I use React.renderToString
with no passed properties it will call AppStore.getAppState()
which won't have anything in it because I still don't understand how would I set the state in my store on the server?
I am still looking for a clean solution that does not involve using third-party Flux implementations like Fluxible, Fluxxor, Reflux.
Use Redux.
Yes! This is where server-side rendering for React comes in. In this article, I want to introduce you to server-side rending (SSR) with React, reasons to use it, and some popular frameworks for rendering React on the server side.
In fact, it was Facebook's release of the React library that popularised a CSR approach to applications by making it more technologically accessible. On the other hand, a web-based app serving mainly static content, like this website, would be expected to opt for an SSR approach.
With respect to Isomorphic React this term means that the web app is made of code that can be rendered on both server and client side, this takes full advantage of benefits from both methods or running websites.
In Client-side rendering, your browser downloads a minimal HTML page. It renders the JavaScript and fills the content into it. Server-side rendering, on the other hand, renders the React components on the server. The output is HTML content. You can combine these two to create an isomorphic app.
Take a look at dispatchr and yahoo's related libraries.
Most flux implementations don't work in node.js because they use singleton stored, dispatchers, and actions, and have no concept of "we're done" which is required to know when to render to html and respond to the request.
Yahoo's libraries like fetchr and routr get around this limitation of node by using a very pure form of dependency injection (no parsing functions for argument names or anything like that).
Instead you define api functions like this in services/todo.js:
create: function (req, resource, params, body, config, callback) {
And actions like this in actions/createTodo.js:
module.exports = function (context, payload, done) { var todoStore = context.getStore(TodoStore); ... context.dispatch('CREATE_TODO_START', newTodo); ... context.service.create('todo', newTodo, {}, function (err, todo) {
The last line indirectly calls the create function in services/todo.js. In this case indirectly can either mean:
This is just the tip of the iceberg. This is a very sophisticated group of modules that work together to solve a tough problem and provide a useable api. Isomorphism is inherently complicated in real world use cases. This is why many flux implementations don't support server side rendering.
You may also want to look into not using flux. It doesn't make sense for all applications, and often just gets in the way. Most often you only need it for a few parts of the application if any. There are no silver bullets in programming!
FakeRainBrigand is correct that the biggest problem with server-side Flux is singletons. Flummox fixes this problem by not using singletons, and enabling you to encapsulate your entire Flux set-up into a single, reusable class. Then you just create a new instance on each request. Combined with a routing solution like React Router, you can make fully isomorphic applications.
Even if you don't want to use Flummox, the source is easy to grok and you could use that as a guide to whip something up yourself:
https://github.com/acdlite/flummox
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With