As my blogging history demonstrates, I am a big fan of React, the awesome JavaScript library for building user interfaces. In this post I take a quick dive into one feature of that library, the function component.
Originally there was only one type of component in React: the class component. It must extend either React.Component
or React.PureComponent
:
class MyClassComponent extends React.Component {
render() {
return <p>Cats are great</p>;
}
}
Later, in the version 0.14 release, function components were introduced:
const MyFunctionComponent = () => <p>Cats are great</p>;
The terminology for this latter type of component varies and has included stateless functional component (SFC), stateless pure-function component, stateless component, and functional component; the React documentation refers to them as function components. These varied names reflect the restrictions that function components have compared to class components. They do not have access to state (in particular as implemented in class components), do not have lifecycle methods, cannot be error boundaries, and the ref attribute cannot be used on them. Conversely, a class component can implement lifecycle methods, can use state, can be an error boundary, and the ref attribute can be used on them.
The primary motivation for adding function components was optimization:
Interestingly, it was only with the release of React version 16 that function components began to be treated differently to class components. They initially behaved as per class components: a backing instance was created for each use of the function component and lifecycle methods checks were made. (The backing instance is required for a class component because it needs to be instantiated to be used; it cannot be used as-is.)
In React version 16, there are no longer backing instances and no unnecessary lifecycle methods checks are made. This means less memory usage and less code executing in the render phase, although,in the scope of your entire React app, these are not game-changing optimizations. Nevertheless, it represent the start of a longer journey:
One way that this compiler could operate is to inline function components so that, for a given higher level component, it could create one large function component that includes the inlined code of the child function components. This is an optimization that is simply not possible with class components, because of the required backing instance and the potential use of lifecycle methods.
A footnote in the history of the function component is that there was initially an expectation that the function component would behave similarly to PureComponent, in that it would only be invoked if the props passed to it compared as not equal to the props previously passed to it. All things come to those who wait: React version 16.6 introduced React.memo, a way to achieve this for function components.
Finally, the future of the function component is looking very interesting; the future is Hooks:
Hooks is an API available to function components that enables the React team to continue the optimization work that relies on components being functions, adding as it does features and component lifecycle participations that have previously only been available to class components. In this way function components should come to dominate in a React app, potentially with class components being removed from the core React distribution to be available only by installing a separate package. This really would represent a major evolution for React, one that started quite simply with the introduction of the function component in React version 0.14.
# Comments
Comments on this site are implemented using GitHub Issues. To add your comment, please add it to this GitHub Issue. It will then appear below.