3

5 Advanced React Patterns

 3 years ago
source link: https://javascript.plainenglish.io/5-advanced-react-patterns-a6b7624267a6
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

5 Advanced React Patterns

An overview of 5 modern advanced React patterns, including integration codes, pros and cons, and concrete usage within public libraries.

Photo by Ferenc Almasi on Unsplash

Like every React developer, you’ve probably already asked yourself one of the following questions :

  • How do I build a reusable component to fit with different use cases?
  • How do I build a component with a simple API, making it easy to use?
  • How do I build an extensible component in terms of UI and functionality?

These recurring questions led to some advanced patterns throughout the React community.

In this article, we will see an overview of 5 different patterns. In order to facilitate the comparison, we will use an identical structure for all these patterns :

We will start with a small introduction, following by a real code example (Based on the same simple Counter component).

All the source code is accessible on this github repository : https://github.com/alex83130/advanced-react-patterns.

We will list the Pros & Cons, then define two factors within a section called “Criteria” :

  • Inversion of control: Level of flexibility and control given to the users of your component.
  • Implementation complexity: Difficulty for both you and users to implement that pattern.

And finally, we will discover some examples of public libraries using the pattern in production.

During this article we will consider the situation of a React developer (You) building a Component for other developers. Therefore, the actor “users” refers directly to these developers (And not the final user which will use your website/application).

1. Compound Components Pattern

This pattern allows creating expressive and declarative components, without unnecessary prop drilling. You should consider using this pattern if you want to make yourcomponent more customizable, with a better separation of concern and an understandable API.

Example

Github: https://github.com/alex83130/advanced-react-patterns/tree/main/src/patterns/compound-component

Pros

  • Reduced API Complexity: Instead of jamming all props in one giant parent component and drilling those down to child UI components, here each prop is attached to the SubComponent that makes the most sense.
1*fNxmemv7z_s7M9n1xOyxPg.png?q=20
5-advanced-react-patterns-a6b7624267a6
  • Flexible Markup Structure: Your component has great UI flexibility, allowing the creations of various cases from a single component. For example, the user can change the SubComponents’ order or define which one should be displayed.
1*X2NPGy2TRJ1MsZbkR7VACA.png?q=20
5-advanced-react-patterns-a6b7624267a6
  • Separation of Concerns: Most of the logic is contained in the main Counter component, aReact.Context is then used to share states and handlers all across children. We get a clear division of responsibility.
1*NxH5i3ugYXxlPR4NO9q_0Q.png?q=20
5-advanced-react-patterns-a6b7624267a6

Cons

  • Too much UI flexibility: Having flexibility comes along with the possibility to provoke unexpected behavior (putting an unwanted Component’s child, making out of order the Component’s children, forgetting to include a mandatory child).
    Depending on how you want the user to use your component, you might not want to allow that much flexibility.
1*5gRvmOA-H4DuDOIbGb25CA.png?q=20
5-advanced-react-patterns-a6b7624267a6
  • Heavier JSX: Applying this pattern will increase the number of JSX rows, especially if you use a linter such EsLintor acode formatter as Prettier.
    It seems not a big deal at a single component scale, but could definitely make a huge difference when you look at the big picture.

Criteria

  • Inversion of control: 1/4
  • Implementation complexity: 1/4

Public libraries using this pattern

2. Control Props Pattern

This pattern transforms your component into a controlled component. An external state is consumed as a “single source of truth” allowing the user to insert custom logic that will modify the default component behavior.

Example

Github: https://github.com/alex83130/advanced-react-patterns/tree/main/src/patterns/control-props

Pros

  • Give more control: Since the main state is exposed outside your component, the user controls it and can therefore directly influence your component.
1*8bmVDqp_KOg347dT_600Pw.png?q=20
5-advanced-react-patterns-a6b7624267a6

Cons

  • Implementation complexity: Before, one integration at a single place (JSX) was enough to make your component working. Now it will be spread over 3 different places (JSX / useState / handleChange).
1*_UoRzY4lRe4WtFvJl8BtTg.png?q=20
5-advanced-react-patterns-a6b7624267a6

Criteria

  • Inversion of control: 2/4
  • Implementation complexity: 1/4

Public libraries using this pattern

3. Custom Hook Pattern

Let’s go further in “inversion of control”: the main logic is now transferred into a custom hook. This hook is accessible by the user and exposes several internal logics (States, Handlers), allowing him to have better control over your component.

Example

Github: https://github.com/alex83130/advanced-react-patterns/tree/main/src/patterns/custom-hooks

Pros

  • Give more control: The user can insert his own logic between the hook and the JSX element, allowing him to modify the default component behavior.
1*hkyJ0eb2NRhX3pUoni0o-w.png?q=20
5-advanced-react-patterns-a6b7624267a6

Cons

  • Implementation complexity: Since the logic part is separated from the rendering part, it is the user who must link both. A good understanding of how your component work is required to correctly implement it.
1*Sxgs_af830xmllTwgW-HKw.png?q=20
5-advanced-react-patterns-a6b7624267a6

Criteria

  • Inversion of control: 2/4
  • Implementation complexity: 2/4

Public libraries using this pattern

4. Props Getters Pattern

Custom hook pattern gives great control, but makes also your component harder to integrate because the user has to deal with a lot of native hook’s props and recreate the logic on his side. The Props Getters Pattern pattern attempts to mask this complexity. Instead of exposing native props, we provide a shortlist of props getters. A getter is a function that returns many props, it has a meaningful name allowing the user to naturally link it to the right JSX element.

Example

Github: https://github.com/alex83130/advanced-react-patterns/tree/main/src/patterns/props-getters

Pros:

  • Ease of use: Provide an easy way to integrate your component, the complexity is hidden, the user just has to connect the correct getter to the right JSX element.
1*auZca0g2eg1Cv7THl6df6g.png?q=20
5-advanced-react-patterns-a6b7624267a6
  • Flexibility: The user still has the possibility of overloading the props contained in the getters to adapt to his specific cases.
1*59EpcnFx_GkrJ3NQ-Zg3CA.png?q=20
5-advanced-react-patterns-a6b7624267a6

Cons:

  • Lack of visibility: The abstraction brought by the getters makes your component easier to integrate, but also more opaque and “magic”. To correctly override your component, the user has to know the list of props exposed by the getters and the internal logic impact if one of them is changed.

Criteria

  • Inversion of control: 3/4
  • Integration complexity: 3/4

Public libraries using this pattern

5. State reducer pattern

The most advanced pattern in terms of inversion of control. It gives an advanced way for the user to change how your component operates internally.
The code is similar to Custom Hook Pattern, but in addition the user defines a reducer which is passed to the hook. This reducer will overload any internal action of your component.

Example

Github: https://github.com/alex83130/advanced-react-patterns/tree/main/src/patterns/state-reducer

In this example we have assocated theState reducer pattern and the Custom hook pattern but you could also use it with the Compound components pattern and pass the reducer directly to the main component Counter.

Pros

  • Give more control: In the most complicated cases, using state reducers is the best way to leave control to the user. All your internal component’s actions are now accessible from the outside and can be overridden.
1*0hLIgVUrAN1ld9Yp3DrJQw.png?q=20
5-advanced-react-patterns-a6b7624267a6

Cons:

  • Implementation complexity: This pattern is surely the most complex to implement, both for you and for the user.
  • Lack of visibility: Since any reducer’s action can be changed, a good understanding of the Component’s internal logic is required.

Criteria

  • Inversion of control: 4/4
  • Integration complexity: 4/4

Public libraries using this pattern

Conclusion

Through these 5 advanced React patterns, we have seen different ways to take advantage of the concept of “inversion of control”. They give you a powerful way to create flexible and adaptable Components.

However, we all know this famous proverb “With great power comes great responsibility” and the more you transfer control to the user, the more your component moves away from the “plug and play” mindset. It is your role as a developer to choose the correct pattern corresponding to the right need.

To help you in this task, the following diagram classifies all these patterns according to the two factors “Integration complexity” and “Inversion of control”:

This article was mainly inspired by the amazing work of

. Take a look at his blog if you are interested in knowing more about each of the patterns. I hope you have found this useful.

Thank you for reading.

More content at plainenglish.io


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK