React.js tips and tricks

After working full-time with React.js for the past 2 years, I've now been 3 times lead React.js developer at 3 Series A startups. It's been a lot of fun, and after having gotten an early start in 2014, it's great to see it blowing up, growing 300% just in 2015 & 2016.

Below are a few of the higher-level things I've learned along the way, hopefully it'll provide you Denkanstoß (food for thought).

Roll your own

Let's say you want to implement an infinite list in React.js. (let's also assume that infinite lists are a solid UX choice)

You may now choose between

When I faced this quiz, ultimately the right answer turned out to be the last one.

After implementing the first 3 I said "screw it" and decided to roll my own. With 3rd party libraries I kept running into problems such as strange markup choices & style structures that made it hard to style the component in line with existing set of components and with seatgeek's implementation in particular -- persistent performance problems (which I later tracked down to part of their code binding to the onScroll event, firing dozens of times per second)

The interesting distinction here seems to be that while jQuery defines things as changesets, which generally "work well enough", with React.js you have to define the exact state at any point in time. You are tightly bound by React's render cycle and can't simply "bind a few events handlers to make it do that thing when that other thing happens". 

Since the app you're working on will generally develop it's very own look & feel, it can be hard to integrate 3rd party components that generally have been extracted from another codebase with its own idea of how to do HTML5, CSS, JS, React.js, browser compatibility, UX & accessibility in the year 2016.

Especially as you customize the behavior down the line, for complex and oft-used interactions, it makes a lot of sense to bite the bullet and roll your own.

It's been my ambition for some time to push forward a unified UI framework under which React developers can rally to concentrate their efforts. I'm happy to see CloudFlare push forward in this space with cf-ui, and hope that more people will push competitors as well as extensions to it.

Break the rules

React.js docs teach us to avoid forceUpdate

Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). This makes your component “pure” and your application much simpler and more efficient.
— https://facebook.github.io/react/docs/component-api.html#forceupdate

But check out Vivian Cromwell's great talk at React.js conf this year. How was her team at Chop able to implement smooth scrolling & updating in a huge infinite list? forceUpdate

Similarly, people will tell you to avoid managing components using this.state anytime you're working with redux.

However, in my experience, this isn't quite right. If some piece of state is specific to a component, and dies with it (i.e. on unmount) feel free to encapsulate it within.

Use data-fetching containers

Check out Michael Chan's and Dan Abramov's great blog posts on this topic:

Presentational and Container Components

Container Components

The gist is, have your representational components (the ones with the markup) be completely unaware of how they get their data, and if their data is even there. This should be handled by a parent component whose job it is to get the data, massage it if necessary, trim it to shape, and finally render the representational component.

React is not a religion

React & Redux generally front-loads a lot of pain.

Wanna have a thing that changes on the page. OK, please define exactly how I should render the entire page under all circumstances.

Want to have a new button? OK, please define a new action identifier, a new action, put the button state into the reducer, as well as the initial state, and now pass the new state through the entire application to where you want it.

Want to have a drag-and-drop interaction? OK, please set aside a day to familiarize yourself with react-dnd and its DragSource, DragLayer, DropTarget & DragDropContext components. Then you can define a collect function that connects the drag source and sets isDragging on the monitor as well as a new ItemType for whatever you want to drag as well as an itemSource which is a plain object with a beginDrag function on it. Now you can use those to instantiate a new DragSource and directly call the class of React component you want to drag around with that.

 
 

You can't deny, there's something seductive about jQuery:

<div class="dragon">DRAG ON ME</div>
$('.dragon').draggable({ grid: [ 20, 20 ] }) 

Boom, done!

But if you try getting a React.js component to be draggable along a grid, you'll wind up writing a crazy 800 line react-dnd monstrosity, that is specific to this one drag UX interaction, and that none of your coworkers will ever want to touch.

Not that would have ever done that.

 

React's core philosophy evolved out of the work Facebook's engineers did on XHP. A PHP extension to help them manage the massive complexity they were dealing with.

As such it only really starts to shine once your project eclipses a certain size & complexity.

What good is beautiful code, thrown away?

Use the best tools

Immutable.js

While there is the initial hurdle, immutable.js will make your code easier to reason about, safer to manipulate, and will save hours debugging. Immutable data structures truly are a godsend.

Webpack

Use webpack, rather than Browserify or requite to pull together your project, react-hot-loader and a plethora of other amazing tools are built on top of it -- it is the way forward.

Babel

Combining babel-preset-es2015 and babel-preset-react allows you to combine your React app with ES2015 features such as fat-arrow functions that automatically bind "this", or decorators such as the great pure-render-decorator.

Thunks

redux-thunk allows you to return thunks rather than action inside actions creators. Inside the thunk (which is basically just a function) you can delay the action, or dispatch depending on certain conditions.

Redux Router

redux-router allows you to keep your react-router state in Redux.

Hot reloading

Hot reloading will make your React development a lot faster: react-transform-boilerplate. It detects which components have changed, and only re-renders those. Rather than waiting 5s for webpack to rebuild your entire project, and waiting for your entire browser to rebuild the site, you get sub-second feedback.

Webpack Dev Server

If you don't fancy Hot Reloading, at least do yourself the favor of using webpack-dev-server. It's been one of those "I wish I had done this sooner" moments for me.

 


That's it! If you have questions or suggestions for improvement, please do not hesitate to contact me at dominik@doda.co