So at this point I’m comfortable with both Blaze/Spacebars and React.
Which view layer do I hitch my wagon to? Things to consider are:
“Community at large” adoption. I’ll have work with people, what does the community use most?
Meteor core support.
Performance on large applications.
I’m not going to build a simple to-do list, I’m going to build out a fleshed out social network so performance is on my mind first and foremost. I appreciate the input from more senior Meteor developers.
react has a better virtual dom implementation. If your app will re-render a lot then react will perform better than blaze. We already had a topic about that.
IMHO they’re both fast enough for most use cases. For me the thing that tips the scales is how easy it is to reason about state in React components. The pure function approach for the view is really nice. This is a nice article explaining that better. Once you learn how to break your components down into small chunks and pass props when possible your views become really easy to manage and even test.
Blaze can organize state and templates if you plan ahead but what ends up happening is that you typically have a reactive template with imperative side effects from things like jQuery and plugins/packages. This can get really hairy in a large app.
After writing several thousand of lines of both i’m staying with React for the view… just my 0.02!
Sure. For an example of DOM side effects, I would have a template that would trigger a bunch of jQuery operations on render. Things like tooltips, Bootstrap widgets, etc… Basically anything in the DOM that Blaze is not directly manipulating itself. To Blaze’s credit, it works really well with other libs and widgets manipulating it’s DOM.
Another issue is keeping track of state that is not saved to the database. Here’s a use case that helps think about the differences in handling state.
Consider this use case. You have to build a large form like the heathcare.gov website where you’re going through lots of ‘steps’ and over a hundred inputs. They would like the form to be filled out before saving it to the database, and it must have the ability to let the user go forward or back in steps, or even skip a step and go back later. Also to keep the form short they want you to dynamically add more sections as needed, for example having an add button to add in an additional set of inputs for each household member.
So this is where React starts to shine. The whole view library is setup to handle state by either holding state in it’s own component or ideally getting state from it’s props passed in by the parent (this makes it easier to test typically). Any change to a components state will trigger a re-render and the re-render cascades down every child (unless canceled by performance methods). This doesn’t sound astonishing but even with non-reactive data the children will be guaranteed to update to their new representation [This video] explains it better than I ever could but the component starts to look like a pure function, it takes arguments (props) and returns it’s representation of the DOM based on state and props.
To be fair, Blaze can handle this problem (the form example). Now that Blaze has template instance variables that can mimic React’s concept of this.state, it’s do-able but more verbose than React. In my experience this is where the simplicity and brevity of Blaze breaks down. Now you have 20 templates with 20 linked JS files, all having to deal with it’s template state lifecycle, and sharing state from another parent template.
Blaze is a nice templating language but the more complex the app the less appealing it is. (it wins 9/10 times for small examples)
This is a really good explanation of the advantage of a “Pure UI”. I’m starting a new project right now, and since React isn’t really officially supported yet I feel very torn. I am forced to pick Blaze because of this, but then again I guess it’s not so bad since it’s only supposed to be an MVP.
@adrianmcli Why not use both? If you roll with FlowRouter you can use FlowLayout to render blaze on a particular route and ReactLayout to render a React component on a particular route. In addition, you could use the react-template-helper package to throw a React component right into Blaze if you need to.
I’ve become accustomed to working with Blaze, but only recently started investigating React. However, from what I’ve experienced so far, I think it may become my go-to view library.
@adrianmcli I’ve also done this as well… React works incredibly well when you have an existing app and you just change out bits and pieces until you get to the point of having everything converted over.
Actually… here’s a great video on doing just that:
@ryanswapp I’m about to try this approach as I’m becoming increasingly frustrated with react-router. From my initial impression, it seems like a sort-of-hybrid approach you mentioned could be the way to go… although i’ll have to figure out a good way to implement a flux uni-directional pattern
Also you can just use regular Flux. I haven’t tried this yet but want to this week. Keep an eye out for the React-ive Meteor repo, i’m going to port that to using Reflux and Alt.
Basically you can start the subscription in the store and have an action trigger it. The subscription has a callback when data changes, you can use this to trigger a store update event. This would cause the subscribed components to re-render of course.
Those components can either pull in their data directly from Minimongo, or if you wanted the store could manage the data and pass it back via the update call.
Additionally if you want your store to survive a hot-reload, you can store the store state in a reactive dict or Session variable.
This would eliminate the MeteorData mixin and would be normal flux.
This is all theory of course I can’t wait to try it out soon.
FWIW FlowRouter has been working great. react-router takes some time to get used to and I think the nested UI feature is better suited for a certain type of app layout.
What’s your developer HR strategy going to be? React is the more performant solution, as per the points described above, and being pure JS; but Blaze is the more ubiquitous architecture, being HTML/JS/CSS. Are you building to make you and a few others rich? Or are you building to change the world? If you want to onramp teams of people, Blaze has some organizational and training advantages over React that will make themselves known once you’re trying to hire developer #5 and developer #16, etc. If you simply want to maximize developer:user ratio, however, and are willing to pay premium for experienced talent and skip or train the junior devs, go with React.
[quote="jxm262, post:11, topic:6921"]
. although i'll have to figure out a good way to implement a flux uni-directional pattern
[/quote]
Update! Just released an example repo of using flux and Meteor. The gist is that you can use Tracker to watch collections and trigger actions like “PLAYERS_CHANGED” and then the players store can re-fetch, causing it’s views to re-render The rewind/replay functionality with the chrome debugging extension is killer!
For others who may be interested, I think this is a really thoughtful thread as well - MeteorFlux Flow
@awatson1978 I can agree with this to a point. The Big thing that I initially liked with Blaze was that it was very friendly to pure html/js syntax. In a way, it reminded me a bit of how easy it was to get started with angular, you just need to know html and input chunk of code wherever you want to run js. But once you start building anything with any decent amount of complexity, it becomes kind of difficult managing the state of the app. I had no problems picking up React very very quickly (much faster than angular). Learning different flux architectures become somewhat difficult however. At this point, I can’t actually think of any reasons why I’d not use React/Flux (given the tradeoffs) since managing state has become soo much easier. That said I also have many issues with React - jsx transpiling, test frameworks/code coverage, etc. all become more difficult especially when trying to integrate with different tools/other frameworks.
Anyway, I’m open to changing my mind but for the moment, I think I’ll go with React with minimal Blaze+FlowRouter. Would love to see some nice code examples comparing all the different architectures, or better yet for Meteor to have a really good example of using React+Some popular Flux architecture.
Yep, agreed. For me the Alt tutorial is what made it click for me. However perhaps it was trying to grok 20 others before lol. Also actually doing it helps 10x more. Once you see the console.logs flowing it starts to make more sense.
[quote="jxm262, post:16, topic:6921"]
But once you start building anything with any decent amount of complexity, it becomes kind of difficult managing the state of the app.
[/quote]
Also i’ve noticed that having separate JS/HTML files makes me want to use less of them… and I end up with html files with > 100 lines of Blaze templates, where React encourages you to have many small components (sometimes several in the same file if it makes sense).
Another perk that’s not 100% obvious up front… composition. Suddenly those verbose bootstrap classes don’t matter when you have row, column, etc… components:
@SkinnyGeek1010 I checked out your flux leaderboard example and was a little bit confused… In the action files you have functions that just return whatever is inputted to them without doing anything. What is the point of that?
Ah yea i’ll change that and add a note. You can also call this.dispatch() instead of returning. Both will create an action and send it to the dispatcher.
Sometimes apps will do things with the data before dispatching it, or even just use an action without a store (perhaps routing with FlowRouter.go or something).
Actions can also can cause several stores to update (otherwise you may think why not just call PlayerStore directly?).
Also if the action is just passing through and not manipulating data, then you can save some keystrokes and call this helper instead:
var LocationActions = alt.generateActions(
'updateLocation',
'updateCity',
'updateCountry'
);
This will do the same thing and just dispatch the action. Thanks for bringing this up! I’ll fix this in the example soon.