7 ms·
Isomorphic JavaScript with React and Node
- Todd 12y agoOverall, 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.
- andrewingram 12y agoI just use superagent for requests, works fine on client and server.
- deleted 12y ago[deleted]
- insin 12y agoThe 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 https://isomorphic-lab.herokuapp.com/addthing
- Todd 12y agoI'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.
- insin 12y agoIt 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.
- williamcotton 12y agoKeep 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 https://www.npmjs.com/package/browser-request and enable and convince 3rd parties to enable CORS on HTTP endpoints.
- Todd 12y agoYou 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.
- jonsterling 12y agolmao, "isomorphic"
- bonif 12y ago+1! (ok with the downvotes)
- dreamdu5t 12y agofrom 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".
- acjohnson55 12y agoWhat is the "shape" that's being referred to, and in what sense is it "equal"?
- jnmuel 12y agoIt'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.
- nox_ 12y agoIn which universe is polymorphism the opposite of isomorphism? Couldn't we just have said "JavaScript that runs everywhere" instead of trying to sound educated?
- aboodman 12y agoWhen 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.
- juandazapata 12y agoAs of May 23rd, 2014, Google bot executes Javascript. You might want to look at the official announcement here: http://googlewebmastercentral.blogspot.com/2014/05/understanding-web-pages-better.html http://googlewebmastercentral.blogspot.com/2014/05/understan...
- serve_yay 12y ago"Sometimes the JavaScript may be too complex or arcane for us to execute" When is "sometimes"? Who knows. Seems like a bad idea to rely on this.
- williamcotton 12y agoSEO isn't the only reason why you'd want to return pre-rendered HTML.
- altano 12y agoI 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.
- Offler 12y agoYes 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.
- tristanz 12y agoAre 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.
- chadpaulson 12y agoI 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-search 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.
- davidwells 12y agoHey Chad, What do you use https://github.com/andreypopp/react-async 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"
- chadpaulson 12y agoUsing 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.