Isomorphic apps isn’t just about writing the code once; its more about maintaining a consistent codebase without having to double-check every single modification in your client or server code to make sure its consistent. In 2015, server-side rendering is simply not an option: being able to deliver HTML that is consistent with you client-side-JS-powered app is mandatory for any public-facing moderately large product, for SEO and mobile performance if not for desktop time to first interaction and accessibility. Anybody who has tried to use PhantomJS or Selenium for server-side rendering at scale also knows that its simply not viable in practice.
The most important problem is data fetching. If all your components are purely local, ie. they don’t depend on remote data fetching, then React.renderToString works great. But in the real world, you most certainly need to wire your components with data from your backend: SQL server, HTTP API, or whatever central data repository you’re using. And data fetching is, by nature, asynchronous. It can rely on sql.query or xhr or whatever fetching mechanism you’re leveraging. But React.renderToString is synchronous. This means it doesn’t make sense to write something like this...