Hello. I’m Sosuke Suzuki of Boostnote maintainer. Boostnote is written in React. Boostnote has been passed time since the development, and there are components that are bloated in many places. Thanks to contributors as well, those components are getting better than before, but they are being Unobtrusive. I’m thinking about doing something about it and this article is about how to do it.
As much as possible “Stateless FunctionalComponent” Since bloated components are hard to read and difficult to manage, it is necessary to divide the components into appropriate sizes. Important things in dividing, eliminate all State that can be omitted and make components as StatelessFunctionalComponent as possible. It is obvious that we don’t hold the state by implementing it as “StatelessFunctionalComponent” instead of extends React.Component.
// Example of StatelessFunctionalComponent
const component = ({hoge, huga}) => (
<h1>{hoge}</h1>
<h2>{huga}</h2>
)
Even if it is inevitable for a component to possess a state to a certain extent, I want to reduce the number of parts that I have to pay attention to state management.
Life cycle is HigherOrderComponent (HOC) For such reasons, it is often easier for people to use “Stateless FunctionalComponent”, but as a disadvantage in creating applications, “Stateless FunctionalComponent” alone can’t handle “lifecycle”. In order to realize that, it is necessary to use “HigherOrderComponent”. HigherOrderComponent is implemented by a function that takes a React component as an argument and returns a React component as an argument. The type signature in like Haskell would be as follows. “hocFactotry” is the name of the function that is the factory of HOC (HigherOrderComponent), W is the React component passed to the argument, and E is the React component of the return value. HigherOrderComponent:: W: React.Component => E: React.Component HOC enhances the abstraction of components and enables further reuse. With HOC you can hook the lifecycle of StatelessFunctionalComponent. You can use it for various other things, but this article does not give a detailed explanation about HOC. The FaceBook official document, Franleplant ‘s React Higher Order Component in depth etc are very easy to understand about HOC. HigherOrderComponent:: W: React.Component => E: React.Component
const InputComponent = ({hoge, boo}) => (
<h1>{hoge}</h1>
<h2>{boo}</h2>
)
function logProps(WrappedComponent) {
return class extends React.Component {
componentWillReceiveProps(nextProps) {
console.log(‘Current props: ‘, this.props);
console.log(‘Next props: ‘, nextProps);
}
render() {
return <WrappedComponent {…this.props} />;
}
}
}
const EnhancedComponent = logProps(InputComponent);
Even if this method is adopted, the component returned by HOC needs to be described using extends React.Component. As the number of components taking this form increases, the class declaration and render become boilerplates.
Easier HOC with recompose
There is a library called recompose. This library is a utility function for HOC and is called react version lodash. There are various functions in this library, they can see the document in recomponse’s Github As mentioned above HOC has various uses, there are many functions for them. Functions related to life cycle are only a few. That’s why I think we can introduce it relatively easily. This area is really like lodash. You can use only the necessary functions as appropriate, and the library itself does not have a complicated structure. The function required to easily implement the life cycle with HOC is the lifecycle function. The lifecycle function has the following type signature. lifecycle :: spec: Object => H: HigherOrderComponent
And it is used like this.
const PostsList = ({ posts }) => (
<ul>{posts.map(p => <li>{p.title}</li>)}</ul>
)
const PostsListWithData = lifecycle({
componentDidMount() {
fetchPosts().then(posts => {
this.setState({ posts });
})
}
})(PostsList);
State in the lifecycle argument is passed as props to the component passed to the HOC argument. Also, the lifecycle type signature can be rewritten as. lifecycle :: spec: Object => W: React.Component => E:Component It is natural that the type of HOC is HOC :: W: React.Component => E: React.Component, but for those using Haskell, it may be easier to understand who wrote it as described above.
Summary If you use HOC with “recompose”, you can easily handle lifecycle with “StatelessFunctionalComponent”. I think that you should use it because it reduces the consideration of the state and makes the description concise. I also wants to divide this component moderately in this way in Boostnote.