Since the announcement of experimental Hooks in React 16.7, they have taken the React community by storm.

I’m a big fun of separating data fetching from components. Usually I have a SomeEntitiesLoader hoc which manage data fetching and refetching when needed. Lets take a look at the simple implementation

Pretty basic. Assume that we sort items on backend and apply search on frontend. So we need to reload only when sort and sortDirection props change. But most likely you have more than one resource to load and wants to reuse this hoc. Let’s rewrite it.

Here it is. To make it reusable I removed redux connect and introduce new props:

loadProps — args we need for data fetching

shouldReload — accept current props and next props, decide should we reload or not

renderProps — props passed to render func

Now we can reuse this component for any kind of loaders. Now when we want to reuse this component we just need to define these props via redux connect or any other thing and we’re good to go.

Here is example usage of this component. We pass props to the loader and then render result according to props passed to loader render prop.

React hooks?

Our SharedLoader works but it’s too big for a so small purpose, we have to call two lifecycle methods and run equals function over props. It also allows us to put here some unrelated logic inside these methods.

What we want to do is to split component into smaller functions based on what pieces are related. According to React hooks doc

With Hooks, you can extract stateful logic from a component so it can be tested independently and reused. Hooks allow you to reuse stateful logic without changing your component hierarchy. This makes it easy to share Hooks among many components or with the community.

useEffect hook

Accepts a function that contains imperative, possibly effectful code.

Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React’s render phase). Doing so will lead to confusing bugs and inconsistencies in the UI.

According to doc function passed to useEffect fires after layout and paint. It’s suitable to running side effects when component did change and we can replace componentDidMount and componentDidUpdate with this hook.

As second argument useEffect accept array of values that the effects depends on. So we can replace or props comparison logic with just passing these values to the useEffect second argument.

Let’s rewrite our SharedLoader

As you can see now we replaced componentDidMount and componentDidUpdate with two effects calls. Only one thing changed in the component API is removed shouldReload prop and added memoProps function.

memoProps is simple function which takes loadProps and transform obj into array of values

const memoProps = R.compose(R.values, loadProps);

Conclusion

Finally we have relatively small component which responsible for only one purpose — reload data when required props are change. We can fully control this logic and reuse it for the most common cases when we need to load data.

Now as we search items on frontend side but if we need to pass this arg to the backend we just need to rewrite our loadProps and memoProps what is really good when it comes to the code ready to change.

Feel free to comment, suggest ideas and add your own insights! Thanks for reading 🙏