When any project grows to a certain complexity, it is bound to face the problem of logic reuse. In React, there are several ways to implement logic reuse: Mixin
, HOC
, Decorator
, Render Props
, Hook
, etc. This article mainly analyzes the advantages and disadvantages of these ways to help developers make a more suitable way for business scenarios.
Mixin
Mixin has been widely used in various object-oriented languages to create a multi-inheritance-like effect for single-inheritance languages, and is perhaps the first approach that developers moving from Vue
to React
can think of. Although React has now abandoned it, Mixin
was indeed a design pattern that React used to implement code sharing.
The mixin method, in the broad sense, is a way to assign the methods in the mixin object to the original object to achieve object mixing, similar to the role of Object.assign()
in ES6. The principle is as follows.
|
|
Using Mixin in React
Assuming that multiple components in our project need to set the default name
property, using mixin
allows us to not have to write multiple identical getDefaultProps
methods in different components, we can define a mixin
In order to use mixin
, you need to add the mixins
property to the component, and then wrap our written mixin
into an array and use it as the value of the mixins
property
The written mixin can be reused in other components.
Since the mixins
property value is an array, it means that we can call multiple mixin
s in the same component. A slight change in the above example gives us
|
|
We can even include other mixin
s within a mixin
.
For example, write a new mixin
DefaultProps
containing the above DefaultNameMixin
and DefaultFriendMixin
|
|
At this point, we can conclude that mixin has at least the following advantages:
- The possibility of using the same mixin in multiple components.
- The possibility of using multiple mixins in the same component.
- Multiple mixins can be nested within the same mixin
However, in different scenarios, advantages can become disadvantages.
- Breaking the encapsulation of the original component and possibly having to go and maintain new states such as
state
andprops
. - The naming in different
mixin
s is unpredictable and very prone to conflicts - May create recursive call problems, increasing project complexity and maintenance difficulties
In addition, mixin
has its own logic for handling issues such as state conflicts, method conflicts, and the calling order of multiple lifecycle methods. If you are interested, you can refer to the following articles:
Higher-Order Components(HOC)
Since mixin
has the above-mentioned shortcomings, React
stripped mixin
and replaced it with HOC
.
HOC
is essentially a function that accepts a component as an argument and returns a new component.
React officially uses HOC
when implementing some public components, such as withRouter
in react-router
, and connect
in Redux
. Here’s an example of withRouter
.
By default, the component must be rendered by Route
route match before this.props
exists, before it has route parameters, and before it can execute this.props.history.push('/next')
to jump to the page corresponding to the route using the functional navigation writeup. The role of withRouter
in HOC
is to wrap a component that is not wrapped by Route
route into Route
, so that the three objects history
, location
and match
of react-router
can be put into the props
property of the component, thus enabling functional navigation jumping.
The principle of withRouter
implementation:
|
|
Use code:
|
|
Since HOC
is essentially a method that gets a component and returns a new component, it can theoretically implement multiple nesting just like mixin
.
For example:
Write a HOC that empowers singing
|
|
Write a HOC that empowers dancing
|
|
Use the above HOC
As you can see above, with a simple wrap using HOC, you can turn the original simple Joy into a nightclub prince who can both sing and dance!
Conventions for using HOC
When using HOC, there are some inkling conventions:
- Passing irrelevant
Props
to wrapper components (passingprops
that are not related to their specific content). - step-by-step combination (avoiding different forms of
HOC
calls in tandem). - include display
displayName
for easy debugging (eachHOC
should conform to a regular display name). - do not use higher-order components in the
render
function (each timerender
, the higher order returns a new component, affectingdiff
performance). - static methods must be copied (the new component returned after a higher order does not contain the static methods of the original component).
- Avoid using
ref
(ref
will not be passed);
Advantages and disadvantages of HOC
At this point we can summarize the advantages of the Higher Order Component (HOC):
- HOC is a pure function, easy to use and maintain.
- Again, since HOC is a pure function, it supports the passing of multiple parameters, enhancing its scope of application.
HOC
returns a component, which can be combined and nested for flexibility.
Of course there are some problems with HOC.
- When multiple
HOC
s are used in nesting, it is impossible to directly determine from whichHOC
theprops
of the child component is responsible for passing. - When parent and child components have the same name
props
, it leads to the problem that the parent component overwrites the child component with the same nameprops
, andreact
does not report errors, which is low developer-awareness. - each
HOC
returns a new component, thus creating a lot of useless components, while deepening the component hierarchy and not making it easy to troubleshoot problems.
Decorator
and HOC
belong to the same schema and will not be discussed here.
Render Props
This is the official React
definition of Render Props
The term “render prop” refers to a technique for sharing code between React components using a prop whose value is a function.
Official example:
|
|
As above, the DataProvider
component has a props
property called render
(it can also be called by other names), which is a function, and this function returns a React Element
that is rendered inside the component by calling this function, then this component uses the render props
technique.
Readers may wonder, “Why do we need to call the props
property to achieve internal rendering of the component instead of rendering directly inside the component”? To borrow from the official React
answer, render props
is not a skill that every React
developer needs to master, and you may never even use this method, but it does exist to provide developers with an additional option when thinking about component code sharing.
Render Props usage scenarios
We may need to use pop-up windows frequently in project development, pop-up windows UI
can be varied, but the function is similar, that is, open and close. Take antd
as an example
|
|
The above is the simplest example of using Model
, even if it is simple to use, we still need to pay attention to its display state and implement its switching method. But the developer really only wants to focus on the business logic related to onOk
, the ideal usage should be like this
The above usage can be achieved by render props
:
|
|
This completes a Modal
with state and basic functionality, and we only need to focus on specific business logic when we use the Modal
in other pages.
As you can see above, render props
is a real React
component, not just a function that returns a component like HOC
, which also means that using render props
will not create the problem of nested components like HOC
, and you don’t have to worry about the override problem caused by props
naming conflicts.
render props usage restrictions
The use of arrow functions in render props
should be avoided because of the performance impact this can cause.
For example:
This is not a good way to write it, because the render
method is possible to render multiple times, and using the arrow function will cause the value passed into render
to be different each time it is rendered, while there is actually no difference, which will lead to performance problems.
So a better way to write it would be to define the function passed into render
as an instance method, so that even though we render it multiple times, it is always the same function that is bound.
Pros and cons of render props
Advantages
props
naming is modifiable and does not override each other.- Clarity of
props
origin. - No multi-layer nesting of components.
Disadvantages
- Cumbersome writing style.
- inability to access data outside of the return statement.
- prone to function callback nesting.
The following code.
Hook
The core of React
is components, so React
has been working on optimizing and refining the way components are declared. From the earliest class components to function components, there are advantages and disadvantages to each. Class components provide us with a complete lifecycle and state, but they are clunky to write, while function components are very simple and lightweight, but they have the limitation that they must be pure functions, cannot contain state, and do not support lifecycle.
The React
team felt that the best way to write components was as functions, not classes, which led to the creation of React Hooks
.
React Hooks
is designed to be an enhanced version of the function component, a full-featured component written without using “classes” at all.
Why class components are “bulky”, to borrow from the official React
example.
|
|
The above is a simple button component that contains the most basic state and click methods, and the state changes when the button is clicked.
This is a very simple functional component, but it requires a lot of code to implement. Since function components don’t contain state, we can’t use a function component to declare a component with the above functionality. But we can use Hook to implement it:
In comparison, Hook
appears to be more lightweight and preserves its own state while staying close to the function component.
In addition to the first hook useState()
introduced in the above example, React
also officially provides hooks useEffect()
, useContext()
, useReducer()
and so on. See the official hooks and their usage for details.
The flexibility of Hook also lies in the fact that, in addition to the officially provided basic hooks, we can use these basic hooks to wrap and customize hooks for easier code reuse.
Hook Pros and Cons
Advantages
- Easier to reuse code
- Cleaner code style
- Less code volume
Disadvantages
- State is not synchronized (functions run independently and each function has a separate copy of the scope)
- Need to use
useEffect
more rationally - Small granularity, need to abstract a lot of
hook
for complex logic
Summary
Except for Mixin
, which is a little bit behind because of its obvious shortcomings, there is no best solution for HOC
, render props
, and react hook
, which all have both advantages and disadvantages.Even for the most popular react hook
, although each hook
looks so short and refreshing, but in the actual business, usually a business function corresponds to multithe hook
, which means that when the business changes, you need to maintain multiple hook
changes, compared to maintaining a class
, the mental burden may be This means that when the business changes, you need to maintain multiple hook
changes, which may increase the mental burden compared to maintaining one class
. Only the way that suits your business is the best solution.
Reference https://juejin.cn/post/6961000054018539550