React JS Best Practices
blog.siftscience.com
blog.siftscience.com
We felt the same way, until we moved away from Facebook's Flux implementation and adopted Flummox[0]. It's singleton-free, so we gained isomorphism for our application with only a tiny bit of extra work, and it hides away the dispatcher (unless you need it, which we haven't despite having over a dozen stores, tonnes of actions and a large number of components).
With Flummox making it so easy, we put all state into a store. This allows us to save application UI state to localStorage, bootstrapping the app into the same position the user was previous, with again no extra effort on our behalf. It's well worth checking out!
Thanks!
Also, can't hurt that the library was designed and implemented in ES6, which is what I've begun moving our architecture towards!
Edit: grammar.
Thinking it only refers to one field and is wrong - when the usage is totally correct (and very applicable) just makes you sound snobbish... and foolish.
Basically, how would you migrate the following code to Flux:
click() { doAction().catch(err => showModal(err)) }Actions describe things that happened in the world and the role of your store is to figure out if that thing that happened is valid or not, and pass the necessary data to components listening for changes.
handleComment(comment) {
if (comment === '') this.dispatch('comment-error', 'empty')
else svc.send(comment)
.then(() => this.dispatch('comment-success')
.catch(err => this.dispatch('comment-error', err))
}
The view/controller (or whatever it's called in React) will then listen to the events and set its state accordingly so that the UI can be re-rendered.It does look quite complicated compared with typical error handling code. Not sure if I misunderstood something or whether this additional layer of message dispatching is worthwhile in most apps.
You can still use singletons on the server, but you have to pass the current user id to every method/event on that singleton. And that ends up being quite annoying.
This new project uses a Rails backend, with React allowing the web to act the same way as any other client (iOS app, Android app etc), and it's so productive to work in.
Pretty much decided I won't be writing a web app any other way for any future work.
These best practices look pretty good, though my advice to any beginners would be to not get too bogged down in worrying whether you're doing things 100% right as React can be pretty forgiving in refactoring later on.
Careful what you wish for!
>>> So true
Understanding the problems mentioned in the slides was literally eye opening. I was already trying to solve the problems with CSS, without fully realizing that I'm solving them. For example, my "solution" to namespaces was creating a naming conventions for all classes/IDs, like ".header-search-box-button" and this approach becomes PITA quickly. Also, after a while I had more and more dead code, which wasn't easy to identify and I couldn't be sure that if I remove some class, I don't have any elements that depend on it. Non-deterministic resolution was also an issue for me - say user was on a page A (therefore had loaded A.css with class .main-button) where particular boxes are blue. If the user goes to page B (we load B.css which also has .main-button) he should have red boxes. But if the user gets back to page A, the boxes that are supposed to be blue are red (browser cached the style and when browser have 2 classes definitions, the one that was loaded the last "wins"). Sure, we could use IDs for everything, bundle all styles into 1 file etc., but bigger sites would have like 5MB CSS file and at the end of the day it's still hard to maintain the codebase.
I'm sure that "normal" way works for regular/medium sites (it worked for a few good years, right?), but I see ton of advantages for using the inline styles in the JS. It's not easy to "convert" to new approach, but I honestly don't look back. As I've said - it's not ideal solution, but a very important step forward.
This is a good 3-part tutorial on react, flux and some other things:
https://www.youtube.com/watch?v=Pd6Ub7Ju2RM
So, to answer your question: Basscss could help with some of the problems with CSS but I think that react solves problem on a higher level and does it better than any other solution we have now.
So, I was thinking using React + BassCSS, and build the class string in my React components. Not sure if it makes sense, but at least it would probably be a bit more manageable and faster to develop than inline styles. Inline styles could be added on top of that of course.
Have you checked Radium (http://projects.formidablelabs.com/radium/)? What don't you like in this approach, if I may ask?
[Linking to the other discussion on this post about CSS and vjeux for future reference: https://news.ycombinator.com/item?id=9515662]
Reasons I'd guess: not being able to use pseudo-selectors and things like :hover; familiarity for designers; easier use of legacy code; benefits of SCSS that would take work to re-implement in js. But I'm curious what your real reasons were!
Otherwise, really good stuff here as someone rapidly picking up on React.
Use componentShouldUpdate well: yes, do. You'll know why you should, quickly enough.
State v.s. props is a great point, but then you need both declarative managed injection via props to initialize or control, mixed with a transient stateful interactivity when the user begins free interactions. Early experiments in "best practices" are efforts like React-Controllables, trying to create components which are isomorphic to state v.s. props driving them.
Everyone is doing their own experiments with how and where data lives and how and where it gets there. That's the nature of webdev, experimenting with pipes. Some cursory words on Flux in your article indicate how vastly unresolved and mysterious the ???->data part of the webapp equation is. "We're experimenting with something Relay like". So way Soundcloud in 2012. Best practice: use react for the next step, data->html.
Best practice: wrap the most boring boilerplate css with your own react components. Oh great, just what everyone needs to go do. Recommendation is to not rely a lot on css, but how, if not global, do we start sharing some style rules effectively? It's disingenuous to offer this as settled "be balanced" best practice, particularly when it's still the hay days of excitement, with new encompassing visions like https://github.com/petehunt/jsxstyle/ just popping up.
Regarding the first, those topics weren't obvious to everyone. Besides no one really benefits when posts are called out for this.
And re the second, these patterns have emerged from one year of maintaining a large app with a growing team. The points mentioned are tips for writing code so that your app will scale, not silver bullets for complex topics such as the general question how to write styles for React. The best practices mentioned in the post are just that, but they're not the only ones.
In the case that a library modifies the DOM, we try to keep React out of it's way. React works best when it has full control of the DOM. In these cases, React components are more of "wrappers" for the 3rd party libraries. Mostly by using the componentDidMount/componentWillUnmount to initialize/destroy the third party library, respectively. And props as a way of giving the parent a way of customizing the behavior of the third party library that the child wraps.
Basically, with GPT you have named slots identified by their DOM element IDs. You can "refresh" a slot any time, which will populate the element if it's empty, or load a different ad.
So we do that when we're mounted. Unfortunately, if the page structure changes, React will re-render the component and blow away the contents -- anything GPT has put in the element is considered alien.
That's fine, we just refresh. The problem is knowing _when_ a render has finished and the ad element is empty. In my testing, React elements would often have a delay after which their changes have been applied to the DOM; so I use setInterval to check repeatedly for an empty element. It seems like a stupid solution, but I couldn't figure out a more solid way; there's no React callback for completed renders.
shouldComponentUpdate() { return false; }
Which would prevent React from re-rendering them after initial mount... any reason why this doesn't work? I do this often when using d3 selections to keep React out of the way and catch incoming props in componentWillReceiveProps instead.
Without the implicitly set key, react creates its own index, so if a change happens in the hierarchy above your component, a new key might be given by react, causing the dom element to potentially be replaced when rendering.
var GoogleAd = React.createClass({
getInitialState: function() {
return {
id: makeUniqueId()
};
},
render: function() {
// Since this is always the same, React won't try to change the contents
return <div id={this.state.id} />;
},
componentDidMount: function() {
googletag.defineSlot('/1234567/sports', [728, 90], this.state.id);
},
componentWillUnmount: function() {
// Clean up the slot and any other resources here
}
});
and then not worry about it.One question: what does that "global Backbone cache" look like?
Without explicit functions to be called, you can't detect state changes and would need polling. This is terrible.
At the end of the day, it's a limitation of JavaScript because unlike with Python, for example, you can't have automagic getter/setter functions. They have to be called as functions.
http://www.html5rocks.com/en/tutorials/es7/observe/
Also you could just re-render whenever any event happens, which is probably when your state changes anyway.
So far exists only on Chrome and Android browsers.
https://groups.google.com/forum/#!msg/reactjs/R61kPjs-yXE/ys...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid...
AmpersandJS, for example, implements its observable pattern in this way:
http://ampersandjs.com/learn/state
That said, I don't think the pubsub/rx/observables pattern is the most optimal for UI development, since it still allows for cascading event chains. Modeling all application state as a large data structure that allows for efficient diffing — which nicely mirrors the diffing react does with both it's internal component tree and diffing with the DOM — is a much more straightforward approach. Just re-render your application 60 times a second, like a game engine, and make that process as efficient as possible.
As another commenter mentioned, explicit `.setState` makes it much easier to see where in your code you're triggering changes. It also helps you think, "okay, I am mutating the state here... is that really what I want to do?"
Because Mithril uses plain JavaScript constructs, you can use standard design patterns and techniques when constructing and managing your components. Everything works beautifully.
You can also use the component abstraction but choose not to use getInitialState/setState -- but our goals are to provide a component abstraction that is flexible enough to meet people's needs while still being restrictive enough for us to build higher-level optimizations around them.