Say you’re building a new application. This application is going to be the thing that updates your company’s product experience to the latest and greatest. You/your designers have mocked up an interaction heavy design, where things updated on the screen will dynamically change other parts of the UI.

You’ve chosen React as your front-end framework. You’ve heard that React’s Virtual DOM implement will help keep your UI snappy and snappy UI is exactly what will give your customers a warm happy glow inside.

You’ve just written the first version of your code to test out your ideas:

class List extends PureComponent {

onClick () {

//...

} onUpdate (item, updatedValue) {

//...

} onMouseOver (item) {

//...

} render () {

return (

<div onClick={() => this.onClick()}>

{ this.props.items.map((item) => (

<Item

key={item.id}

item={item}

onMouseOver={() => this.onMouseOver(item)}

onUpdate={(value) => this.onUpdate(item, value)}

/>

)) }

</div>

)

}

} class Item extends PureComponent {

render () {

const {

item,

onUpdate,

...rest

} = this.props return (

<div {...rest}>

<input

type="text"

value={item.value}

onChange={(e) => onUpdate(e.target.value)}

/>

</div>

)

}

}

You know that React creates a representation of your components and uses it to efficiently update the browser when you provide a new version of this view.

You understand that, whilst its generally more than sufficient in most cases, in some cases you want to improve the performance by using PureComponents to tell React which parts have not changed.

You’ve put in the key attribute for all your items, which should give a hint to React as to which items match to which.

You’ve used ImmutableJS for your state so the shallow compare algorithm that PureComponent uses will be fast and efficient.

However you find that its still not helping, and every update still takes longer than you think it should.

sooooo slow

To help you debug, you’ve installed the React DevTools for Chrome / Firefox.

You click on the little checkbox on the top left corner called ‘Trace React Updates’, which will flash a border around any component that was just updated.

With this feature switched on, you notice that, even though you’ve been a good little front-end developer and have done all the performance best practices, each Item is still being updated every time you type.

Not what was expected

You expected that only the Item thats changed should have a flashing border.

You search the internet for information and realise, “Duh I’m creating a new function every time I re-render List , even though the item itself didn’t change”. You are also amazed that you somehow managed to get code formatting into your internal monologue.

Its obvious once someone points it out

You quickly set out to fix this problem by rebinding the functions in the constructor so each arrow function is only created once. You start by changing the `onClick` handler for the `List` component

class List extends PureComponent {

constructor () {

this.onClick = this.onClick.bind(this)

} onClick () {

//...

} //... render () {

return (

<div onClick={this.onClick}>

//...

</div>

)

}

}

Better yet, you remembered there’s the class instance fields proposal, which allows you to define your onClick handler as an arrow function! Even better, there is a corresponding babel plugin to let you use it today! You play a round of code golf with a giddy sense of nerdish glee.

class List extends PureComponent {

onClick = () {

//...

} //... render () {

return (

<div onClick={this.onClick}>

//...

</div>

)

}

}

Now you feel on top of the world and ready to tackle anything!

You leap head-first into refactoring the rest of your render function to get rid of these pesky arrow functions. But oh noes! When you try refactoring the arrow functions inside the map function in the same way, you run into problems.

So close…

Each of those arrow functions require item to be an argument. Since they require dynamic information that changes when the state changes, you can’t create a bound version of the function in the constructor. Using Function.prototype.bind inside the mapping function would still create a new function every time, putting us back to square 1. What to do…

You could refactor the Item component so that every event handler is given the item as one of the arguments:

class List extends PureComponent {

//...



render () {

return (

<div onClick={this.onClick}>

{ this.props.items.map((item) => (

<Item

key={item.id}

item={item}

onMouseOver={(e, item) => this.onMouseOver(item)}

onUpdate={(item, value) => this.onUpdate(item, value)}

/>

)) }

</div>

)

}

} class Item extends PureComponent {

render () {

const {

item,

onMouseOver,

onUpdate,

...rest

} = this.props return (

<div

onMouseOver={(e) => onMouseOver(e, item)}

{...rest}

>

<input

type="text"

onChange={(e) => onUpdate(item, e.target.value)}

value={item.value}

/>

</div>

)

}

}

Whilst this feels okay for the onUpdate handler, it feels wrong wrapping every possible DOM event handler that the consumer of your Item component could possibly need.

You try another approach. You define a WeakMap in for your List component that holds a weak reference to the handlers that each item needs. This way, only when an item has not been seen before will a new function reference be created:

class List extends PureComponent {

itemEventHandlers = new WeakMap() getItemEventHandler = (item) {

if(this.itemEventHandlers.has(item)){

return this.itemEventHandlers.get(item)

} const eventHandlers = {

onUpdate: (value) => {

//...

},

onMouseOver: () => {

//...

}

} this.itemEventHandlers.set(item, eventHandlers) return eventHandlers

} //... render () {

return (

<div onClick={this.onClick}>

{ this.props.items.map((item) => (

<Item

key={item.id}

item={item}

{...this.getItemEventHandler(item)}

/>

)) }

</div>

)

}

}

You use a WeakMap so you don’t have to manually track when an item is no longer needed and thus its corresponding functions can be garbage collected. Ah the beauty of weak references.

You think, “Hey, why not just store the whole Item component instead of just the event handlers so the render function of the List component is even more efficient”:

class List extends PureComponent {

itemCache = new WeakMap() renderItemComponent = (item) {

if(this.itemCache.has(item)){

return this.itemCache.get(item)

} const component = (

<Item

key={item.id}

item={item}

onUpdate={(value) => {}}

onMouseOver={() => {}}

/>

) this.itemCache.set(item, component) return component

} onClick = () {

//...

} render () {

return (

<div onClick={this.onClick}>

{ this.props.items.map(this.renderItemComponent) }

</div>

)

}

}

Your code now does what you expect it to; Each Item updating only if its item has changed.

When you go to check React DevTools though, all the `Item` components are still flashing.

It works fast now, but DevTools still not showing what you expect.

Looking closer, you notice that only the inner icon for the component you’ve changed blinks. You find an open issue that hopefully will be resolved soon to provide greater visibility and understanding to your code.

You’re now not sure if you’ve written an incredibly clunky hack or a brilliantly engineered solution. You now write a blog post showing what you’ve done.

You hope people will write in the comments with their experiences, and what their solutions were. You thank any potential readers for their time.