React Stateless Functional Components: Nine Wins You Might Have Overlooked

Written by housecor | Published 2016/03/01
Tech Story Tags: javascript | react | es6

TLDRvia the TL;DR App

React .14 introduced a simpler way to define components called stateless functional components. These components use plain JavaScript functions. Here’s the before and after in ES6:

27 lines vs 21 lines isn’t the big story… Also, note that the nested `sayHi` function on the right should admittedly be avoided for performance reasons. See comments for why.

The differences above may seem subtle at first glance, but cutting the noise is a big win.

Here’s why.

**No Class Needed**Frankly, I think the drama around ES6 classes is overblown. But I do agree that plain functions are generally preferable, and eliminating the class related cruft like extends and the constructor in the example above are a nice win.

No this KeywordAs you can see above, the stateless component is just a function. Thus, all the annoying and confusing quirks with Javascript’s this keyword are avoided. The entire component becomes easier to understand without the this keyword. Just compare the click handler in each approach:

onClick={this.sayHi.bind(this)}>Say Hi</a>onClick={sayHi}>Say Hi</a>

Note that the bind keyword isn’t necessary for the stateless component. Dumping classes eliminates the need for calling bind to pass the this context around. Given how confusing JavaScript’s this keyword is to many developers, avoiding it is a nice win.

Oh, as a side note, there are five different ways to handle binding in React. Here’s a short post on the merits of each approach.

**Enforced Best Practices**Stateless functional components are useful for dumb/presentational components. Presentational components focus on the UI rather than behavior, so it’s important to avoid using state in presentational components. Instead, state should be managed by higher-level “container” components, or via Flux/Redux/etc. Stateless functional components don’t support state or lifecycle methods. This is a good thing. Why? Because it protects from laziness.

See, it’s always tempting to add state to a presentational component when you’re in a hurry. It’s a quick way to hack in a feature. Since stateless functional components don’t support local state, you can’t easily hack in some state in a moment of laziness. Thus, stateless functional components programatically enforce keeping the component pure. You’re forced to put state management where it belongs: in higher level container components.

**High Signal-to-Noise Ratio**As you can see in the image above, stateless functional components require less typing. This translates less noise. As I discuss in “Writing Code for Humans”, great code maximizes the signal-to-noise ratio. The 27 line component became 21 lines, a ~20% reduction. You can go a step further on simple components. With a single line return statement, you can omit the return and curly braces. If you do this and also use ES6 destructuring on props, the result is nearly all signal:

It’s a function that takes a parameter and returns markup. Nice. Seriously, could this feasibly be any cleaner?

Code Completion/IntellisenseIf you destructure your props in ES6 as I did in the example above, then all the data you use is now specified as a simple function argument. This means you also get improved code completion/intellisense support compared to class-based components.

Bloated Components and Poor Data Structures Are Easily SpottedWe all know a function that takes a lot of parameters is a code smell. When you use ES6 destructuring with your stateless components, the argument list clearly conveys your component’s dependencies. Thus, it’s easy to spot components that need attention. In this case, you can either break up the component or rethink the data structures you’re passing around. Sometimes a long list of props can be easily resolved by passing an object instead. But if the props aren’t logically related enough to justify a single object, then it’s likely time to refactor the component into multiple separate components.

**Easy to Understand**As we’ve just seen, when you see a stateless functional component, you know it’s simply a function that takes props and spits out HTML. Even if it contains a lot of markup and nested functions inside the render, it’s conceptually simple. It’s a pure function. This leads to the next big win…

**Easy to Test**Since it’s a pure function, your assertions are very straightforward: Given these values for props, I expect it to return this markup. So for the example HelloWorld component, I can assert that when the render function is called with the value of ‘Cory’ for props.name, it returns a div with ‘Hi Cory’ inside.

With React’s stateless functional components, each component can be easily tested in isolation. No mocking, state manipulation, special libraries, or tricky test harnesses are needed.

PerformanceFinally, stateless functional components may soon offer improved performance as well. Since there’s no state or lifecycle methods to worry about, the React team plans to avoid unnecessary checks and memory allocations in future releases.

Update: With React 16.6+, you can declare “pure” functional components via React.memo. And with Hooks in 16.7, functional components transpile smaller too.

Even today, functional components transpile down to less code than class components, which means functional components = smaller bundles:

Class components compile down to at least 20 lines of code. The equalivent functional component requires only 6 lines of code. Result? Smaller bundles.

Improved performance with superior syntax, testability, and readability? Sign me up!

Any downsides?

Yep. See my other post, “7 Reasons to Outlaw React’s Functional Components”, for the potential downsides to consider.

Summary

For all these reasons, we should strive to use stateless functional components wherever possible. Stateless components are just the latest reason why I love teaching React. React stateless functions offer the most elegant approach I’ve seen for creating a reusable component in any popular framework. Yes, even including Angular 2.

Are there other wins I’m overlooking? Downsides to consider? Chime in via the comments below.

Cory House is principal consultant at reactjsconsulting.com. He is the author of “Building Applications with React and Redux in ES6", “Building Applications with React and Flux”, “Clean Code: Writing Code for Humans” and multiple other courses on Pluralsight. He is a Software Architect at VinSolutions and trains software developers internationally on software practices like front-end development and clean coding. Cory is a Microsoft MVP, and founder of outlierdeveloper.com.


Published by HackerNoon on 2016/03/01