35 comments

[ 2.8 ms ] story [ 38.9 ms ] thread
Overall, I think React is a great step forward in supporting isomorphic apps. The last hurdle, at least for me, is its limited support for asynchronous rendering server side.

The biggest problem is that renderToString follows a different component life-cycle path. In particular, componentDidMount isn't called. Although this makes sense (there is no actual DOM to mount, just the virtual DOM), this is typically where server-side interaction is handled. Without this life-cycle hook, it's more difficult to build components that behave similarly on the client and the server.

In addition, one must set up abstractions around things like API request transports (e.g., jQuery on the client and request on the server) that have different environmental requirements. This part is more manageable.

I just use superagent for requests, works fine on client and server.
(comment deleted)
The fact that componentDidMount only gets called on the client seems like it would make it a good place to hook up progressive enhancement after rendering a basic isomorphic version on the server (e.g. a <select multiple> which you enhance with dynamic features only when JavaScript runs on the client) - for server rendering, it would be too late as you only get one render and need to do everything up front.

I've been playing [1] with isomorphic forms using react-router - it uses a static willTransitionTo() hook on the constructor of components which do route handling for the equivalent of request handling, which seems to work well in the limited cases I've tried so far.

For API requests, you can use a request library which has the same API on client and server - superagent and axios seem to work well.

[1] https://isomorphic-lab.herokuapp.com/addthing

I'm also using react-router. I've been pretty happy with it. I will take a look at willTransitionTo again. In the meantime, I'm doing what you suggest--rendering a basic initial view.

In the end, you are only going to be able to go so far on the server before you have to wait for the client side mounting event. You can render a complete page, with forms and the rest, but it won't be interactive until the mount anyway.

It can be! That's one of the the benefits of the isomorphic approach - for the bits you want to use it in, it should degrade to regular forms 'n links round-tripping.
Keep your server-side interactions (aka state) outside of the scope of your components and pass in data as properties.

There is an intrinsic connection between state and external environment that must be grasped before you can start building isomorphic modules.

I'm not sure why jQuery and React would ever be used in the same project. If you want an isomorphic solution to retrieving data check out https://www.npmjs.com/package/browser-request and enable and convince 3rd parties to enable CORS on HTTP endpoints.

You make valid points and, in general, the top-down prop passing convention is the recommended approach with React. This works well if most of your state can be managed client-side with, e.g., Flux stores. There are some cases, though, such as large scale paginated data sets, that require out-of-band requests to a service (even if they are managed through stores). This is the case that's problematic. For these components, I just render out scaffolding and a loading indicator.

Thanks for the recommendation. The only reason for jQuery is the occasional external dependency and the XHR wrapper.

lmao, "isomorphic"
+1! (ok with the downvotes)
from the Greek "isos": "equal", "morph": "shape". Do you have a better suggestion?

I don't see anyone complaining about the use of the word "function" instead of "subroutine".

What is the "shape" that's being referred to, and in what sense is it "equal"?
It's essentially the opposite of polymorphism. Polymorphism says that if you look at the same thing in two different contexts you should get two different results. Isomorphism says that if you look at the same thing in two different contexts you should get the same thing. Here the contexts are server and client.
In which universe is polymorphism the opposite of isomorphism? Couldn't we just have said "JavaScript that runs everywhere" instead of trying to sound educated?
When you want to refer to the same concept over and over, it helps to give it a name.

Other examples: ajax, lamp, nosql, soa ... they may be buzzwords, but they are helpful. I don't see the problem here.

Isomorphism was already a word before Nodejitsu abused it. Your examples are acronyms and abbreviations.

Nevermind that this concept is not even worth a name.

It is common to repurpose words this way. I think it is called 'metaphor'. See also: half the names in technology and all nearly every apple product name.

Anyway, I find the term useful.

Metaphors make sense, that reusing of isomorphism doesn't, however you quote Greek words to justify your means.
It's just that "isomorphism" has a very well-defined meaning, and this is essentially cargo-culting mathematical-sounding language to refer to something that has nothing to do with isomorphism at all (at least, not in the sense that the word is usually meant).

You can do all the reverse etymology you want, but in the end, we all know this is just a word that JavaScript kids are using because it makes them feel cool.

This sort of reminds me of when that weird kid nobody likes tries on a new nickname (like "The Chief" or "Serpent" or "T") and I have to kindly say, “Hey bingo/bud, I'm really sorry, that nickname is just not happening".

In light of my previous reply, I wonder why you think appropriation of terms is okay going one way but not the other. It really seems a bit like bullying. Why can't the weird kid call itself whatever the weird kid chooses? It seems like the job of a bully to say "no way twerp, you can't use 'The Chief', that's only for cool kids to use". I don't know why you'd willingly take on that role.
No one is stopping the weird kid from reappropriating words and nobody is being bullied. People are simply objecting to a use of the word. This is no different than people objecting to using the word literally to emphasize a figurative expression.

To your other point, I'm not against reappropriating words in different contexts to describe ideas metaphorically. In this particular case, isomorphic is already defined in a programming/math context. You're not so much reappropriating a definition to a new contract as you're making an existing word sound more ambiguous in the same context by diluting it. I think the reason people are so passionate about not diluting this term is because they want people to understand and really appreciate the value of isomorphisms. They're not being bullies to make themselves feel superior, they're trying to protect an idea from being misrepresented.

platform agnostic, environment agnostic, cross-platform.

We already have words that mean exactly what is trying to convey. Taking a word that doesn't and adding it to that pool (especially when isomorphic has a meaning in mathematics and computer science already - e.g. two functions are isomorphic if for all inputs they produce the same output, even if their implementation differs) is a bad idea.

Edit: And we who argue that isomorphic is not the right word for this concept already know what the word means. We also know what the words in the definition mean, and also its usage, which is as a relation between two elements in the same set. Saying something is isomorphic on its own is against the definition.

I think that's a well-established name for rendering the same JS both in the back-end and front-end. Would some other name work better?
It's just really confusing, since it has literally nothing to do with the established meaning of "isomorphism". Also kind of cringe-y, since you know it's just JavaScript people trying to sound cool. Another commenter suggested "JS which runs everywhere"; that's cool, or I'd even suggest something more mundane like "shared code".
I don't think the "it already had an established meaning" argument is very tenable, especially not when we're talking about mathematical terms. Maths freely borrows terms that have very well established meanings. E.g., "category" has an ancient and well established meaning, but that didn't stop it from being appropriated for "category theory". Category theorists also seem to have appropriated the term "categorical" even though it has a very specific and firmly established meaning in logic. "Functor" was appropriated from an established term that was in use by logicians and linguists. "Topology" was taken over from botanists. Categorial "Monads" have nothing to do with Leibniz (that I can tell), nor "arrows" with everyday arrows of any sort, and the wikipedia article on category theory even begins with the following caution:

>Several terms used in category theory, including the term "morphism", differ from their uses within mathematics itself

There may be other aspects of the appropriation of sexy math terms which you find problematic, but the mere act of borrowing established terms doesn't seem problematic in its own right.

fwiw, I don't like JavaScript and I am interested in and partial to mathematically and logically grounded languages. otoh, I don't care what names JS developers give to their constructs either.

I'm with this guy. How about "server/client apps?" It only costs 3 characters to actually convey information.
I gave this tutorial (and React) a shot, since I find the concept of server/client apps intriguing, but stopped reading halfway through the Flux documentation.

I can't decide whether I love or hate React w/ Flux, but the one thing I'm sure of is that the documentation was written by someone who had pain in some framework I haven't had experience with. I've used Knockout extensively in a medium sized web application and reasoning about the source of data updates and dependency invalidation hasn't really been a problem at all. And that's the perfect example of the data-binding and dependency modeling which seems to be what React is eschewing. shrug Either way I'm still intrigued and will give it another go when I have more free time.

Yes I think it depends on what level of complexity you are dealing with, Flux is an overhead for low complexity components. Once you get into higher complexity you need better abstractions and structure then what KO on it's own provides you.

In other words there is no one size fit all solution, but I think we all know that already.

Are there any actual examples of full-fledged isomorphic React applications? All the examples I've seen are toys. I mean isomorphic routing, flux architecture, async data access, etc.
I recently published an isomorphic React / Flux demo which features all of the above, including progressive enhancement and document title management.

https://github.com/chadpaulson/react-isomorphic-video-game-s...

That said, I am currently working on a more refined approach to isomorphic flux and async in a new project that I hope to open source later.

Hey Chad,

What do you use https://github.com/andreypopp/react-async for?

I was trying to wrap my head around that the read the warning:

"WARNING: Keeping data in React component's state is a bad idea. React component's state is for purely UI state, like "if this dropdown openned or closed?". In light of that, React Async is an anti-pattern so you shouldn't use it unless you are 100% sure you need it"

Using react-async allowed me to make an aysnc request to an API before initializing the component and setting initial state. The library also enables the client to bootstrap / hydrate initial state generated on the server.

I am currently working on a new project utilizing different modules (alt instead of reflux and react-router instead of react-router-component) which does not utilize react-async.