React Cookbook: hooks dependency injection –How we do it with our platform Joyn

Oleksandr Fedotov
ProSiebenSat.1 Tech Blog
4 min readJan 29, 2021

When creating reusable React components, developers often encounter challenges when a component with hooks requires minor changes in behavior for different use cases. While adhering to the rules of hooks comes with limitations, this React Cookbook article explores a new approach.

It describes how the team at Joyn* deals with the challenges and their approach to finding the best possible solutions. The article illustrates this technique using a case study that includes different data-fetching scenarios for a button component.

*Joyn has been a 100% subsidiary in the Entertainment segment of ProSiebenSat.1 Media SE since 2022. This means that all existing and future tech content about Joyn can also be found on the ProSiebenSat.1 Tech Blog.

Photo by Bill Oxford on Unsplash

According to the rules of hooks, you may not nest hooks inside of if statements or loops. Of course, you can ignore it and wrap the hooks with an if statement. That would work until a certain point but we definitely do not recommend that approach.

Yet, there is another way, which we will showcase in this article. It allows you to override hooks inside of your components without wrapping them with an if statement.

Case problem

Let’s say we have three types of data-wrapping components for a Button component:

  1. Fetches data immediately when is mounted
  2. Fetches data when visible
  3. Fetches data only when user information has become available

The very first and straightforward approach is to just create three different components to solve these three use cases. This approach works and is preferable when you have very different logic inside those wrappers so that you almost don’t have code duplication.

However, when you have many common parts it would be nice to somehow reuse the code.

This is how the data fetching code for the first Button wrapper could look like:

Very simple one-liner, however, there is some code hidden behind the useQuery hook. Don’t think about it too much, it’s an abstraction that allows us to hide some not-important implementation details. If you’re interested to know more you can check the official docs of Apollo Client.

The second `Button` wrapper code will be a little more complex:

So in the code snippet above, we have a useLazyQuery hook which is similar to useQuery, except that it’s fetching data only when loadData is called.

You can read more about it here.

Another hook we used here was useVisibilityChange. It’s an incomplete code example, but imagine it will be triggered once a component becomes visible.

So by default, isVisible is false and once the user scrolls to the component where this hook is used isVisible will become true.

It’s easy to notice that in the second, case we have quite a different part responsible for fetching the data, which is also attached to the component visibility update.

Here is the third code snippet:

How to unite all three different approaches

There are different ways to unite all three cases above into a single component. One would be to use if statements. But it’s also possible to use JS closures that have a static reference to the corresponding hook. This way the component will use either one of the hooks without any if statements.

Using the getButtonWithData in the component factory (a very similar approach as HOCs have) we can easily create three different components, which can subsequently be used inside of the application. This is how the first type of button will look like:

Below is an updated version of the second type of button that fetches data when it becomes visible:

The third type of the button that fetches data when user information is available will be implemented similar to that:

In these synthetic component examples, this approach might look like over-complicating things, but it pays off with more complicated hooks or larger components, where it brings a lot of value and simplicity into the code.

Testing the parts in isolation will also be easier as you’ll need to test only your custom hooks as basic functions as well as the base component.

Conclusion

The described approach might be controversial, however, there are cases when applying it allows reducing code complexity. This way it’s possible to eliminate a lot of code duplication. There are also cases when keeping three different components that would make things easier and more maintainable.

At Joyn, we take an iterative approach, so we usually first implement something using KISS (keep it simple & stupid) principle. Afterward, we look at the result, determine ways to improve it, and iterate over.

+++ This article was already published by the author on the former Joyn Tech Blog and was moved to the P7S1 Tech Blog in January 2021 and integrated here. From now on you will find all the content regarding Joyn on the P7S1 Tech Blog. +++

--

--