React Advanced components
The index
In the React component construction process, there are often scenarios where a certain type of function needs to be shared by different components. In this case, the topic of abstraction is involved. There are many abstraction methods under different design concepts.
Mixin
Mixin features have been widely available in various object-oriented languages. In Ruby, for example, the include keyword is mixin. Is mixing a module into another module, or into a class. Why would a programming language introduce such a feature? In fact, some of the older OOP languages, including C++, have a powerful but dangerous feature of multiple inheritance. In modern languages, in order to weigh the advantages and disadvantages, most of the multiple inheritance is abandoned and only single inheritance is adopted. However, single inheritance has many inconvenient places in realizing abstraction. In order to make up for the deficiency, Java introduced interface. Other languages introduce techniques like mixins.
The problem of a Mixin
From the above code, it is not difficult to see that for the generalized mixin method, it is to mount the methods in the mixin object to the original object in the way of assignment, so as to realize the mixing of the object.
From the above implementation, we can think of the extend or assign methods in the Lodash libraries or the Object.assign() methods in ES6.
React does not recommend the use of Mixins for code reuse. Mixins have a number of disadvantages. First, Mixins can cause naming conflicts. It’s possible to use a method with the same name in two mixins, which makes one of them invalid, and all you can do is change the name of one of the methods. On the other hand, a mixins may start out simple, with only one function to implement, but become very complex as the business becomes more complex and more methods need to be added to it. In response to these concerns, the React community has come up with a new way to replace mixins: higher-order components.
concept
When it comes to higher-order components, we have to talk about higher-order functions first. Higher-order functions are functions that meet at least the following conditions. In javascript, which is a first-class citizen language, the use of higher-order functions is very much, such as our usual callback function and so on, which uses the knowledge of higher-order functions. Let’s start with a simple higher-order function
From the above code, it is not difficult to see that for the generalized mixin method, it is to mount the methods in the mixin object to the original object in the way of assignment, so as to realize the mixing of the object. From the above implementation, we can think of the extend or assign methods in the Lodash libraries or the Object.assign() methods in ES6.
Higher-order components are used in the same way as higher-order functions. Higher-order components take a component as an argument, do a series of things to the component in the function, and then return a new component as the return value. HOC is an advanced technique used in React to reuse component logic. HOC itself is not part of the React API. They are a pattern that emerges from the very nature of React’s conception, a pattern that inevitably arises from the combinatorial nature of React itself. Specifically, a higher-order component is a function that can take a component as an argument, do a series of things to the component in the function, and then return a new component as the return value. When we used the React-Redux framework in our project, we had the concept of connect, which was a higher-order component. The concept of withRouter, similar to the react-router-dom concept, is also included.
Decorator mode
So let’s do the simplest demo
The component used the simpleHoc wrapper to hit a log… SimpleHoc is a higher-order component, by receiving a component class (Usual) and returning a component class. And we can actually see that we can do a lot of things with this function. And the return component also has its own lifecycle, function, and we saw that it is possible to pass props to WrappedComponent(WrappedComponent).
Higher-order components can be seen as implementations of the Decorator Pattern in React. ES7 adds a decorator property to the Wrapper Pattern that allows new functionality to be added to an existing object without changing its structure, denoted by the @ character for more concise writing. The above example can be changed to the same effect. Of course, compatibility is a problem, and it’s usually compiled through Babel. Babel provides plugin, transform-Decorators-Legacy.
implementation
There are two ways to implement higher-order components: property proxy and reverse inheritance.
Property broker: Higher-order components operate functions through the wrapped React component
Property brokers have four common functions:
-
Operating props
-
Access component instances through refs
-
To extract the state
-
Wrap WrappedComponent with other elements for purposes such as layout
State can be extracted by passing in the props and callback functions. After using the ppHOC decorator, the component props is given the name attribute. Value and onChange can be added to the input using the following method
Reverse inheritance: Higher-order components inherit from the wrapped React component.
Reverse inheritance can hijack the render content of the inherited class, modify it, filter it, and return the new display content. It’s called render hijacking because HOC controls the render output of WrappedComponent and can be used for all sorts of things.
Code as above. Higher-order components return components that inherit from WrappedComponent. Because the WrappedComponent is passively inherited, all calls are reversed, which is where this method comes in. This approach is not quite the same as property brokering. It is implemented by inheriting WrappedComponent, and the methods can be called sequentially through super. Because it relies on inheritance. HOC is called in the same order as a queue. Read, add, edit, and delete any React element output by Render props Read and modify the React element tree output by Render conditionally wraps styles into the element tree, just as the props Proxy wraps other elements
Application scenarios
1. The UI of the two pages is almost the same, the function is almost the same, only a few operations are not quite the same, but write two page-level components with a lot of coupling
2. I wrote A component A before. After it was put online, A new requirement was added
3. When you can’t solve a Container or even are not very elegant
4, implement a function to return records from loaclStorage
Mobx-react, react-redux
A).Container can’t solve it or even not very elegant. In most cases, the same effect can be achieved by using a layer of Container components, such as props and render hijacking. But there’s a big difference. For example, we now have a container with two functions: add styles and add handlers to wrap the Usual.
The @Observer decorator wraps a component as a high-order component. After passing it to MyComponent, mobx-React performs various processing on its life cycle. The minimum granularity of rendering is achieved by calling forceUpdate to refresh. Mobx advocates a data reference, while Redux advocates immutable, returning new objects each time.
C). The react – connect in the story
D).connect([mapStateToProps],[mapDispatchToProps],[mergeProps],[options])(WrappedComponent)
For example, we wired the component ComponentA to Redux like this:
const ConnectedComponentA = connect(mapStateToProps,mapDispatchToProps)(ComponentA);
We can break it down:
// Connect is a function, as is enhance, the return value
const enhance = connect(mapStateToProps, mapDispatchToProps);
// The function returned is a higher-order component that returns a new component associated with the Redux store
const ConnectedComponentA = enhance(ComponentA);
The connect function connects a React component to Redux’s Store
This function connects a React component to Redux’s Store. During the connection, connect uses the mapStateToProps parameter to extract the state required by the current component from the global store and convert the state to the props of the current component. In addition, the Action Creators of Redux, which is needed by the current component, was passed to the current component as props through the parameter mapDispatchToProps.
conclusion
1. Advanced components do not modify or copy the behavior of subcomponents. Composition is recommended.
2. Add a class name to hoc to facilitate the debugger.
3. Static methods should be copied.
Refs will not be passed.
5. Do not use higher-order components inside the Render method