React High-level component HOC
😊 article is slightly longer, do a good heart preparation oh, recommended reading 15 minutes.
define
- HOC is actually a function that takes a component as an argument and returns a wrapper component as a return value
- The same functionality is required in multiple different components
- Higher-order components and decorators are one pattern, so higher-order components can be used as decorators
role
- It doesn’t require ES6 or other features that need to be compiled. Where there are functions, there is HOC.
- Debug is friendly and can be displayed by the React component tree, so it’s clear how many layers there are and what each layer is doing.
Added notes for decorators
A Decorator (@) is used in many of the following cases. A Decorator is a function that modifies the behavior of a class.
More usage may refer to Jane books an article: www.jianshu.com/p/275bf41f4…
Basic form
const EnhancedComponent = higherOrderComponent(WrappedComponent)
function hoc(WrappedComponent) {
return class HOC extends React.Component {
componentDidMount() {
console.log("hoc");
}
render() {
return<WrappedComponent />}}} class extends React.Component {render() {
return <div></div>
}
}
exportdefault hoc(ComponentClass); // Use @hoc as a decoratorexport default class ComponentClass extends React.Component {
//...
}
Copy the code
Common use
- Props Proxy: High-level components perform operations on Props of ComponentClass
- Inheritance Inversion: Higher-order components inherit from ComponentClass
Common functions of the properties Proxy
- Operation props: You can add, delete, modify, or check the props of the original component without damaging the original component
// Add new propsfunction ppHOC(WrappedComponent) {
return class PP extends React.Component {
render() {
const newProps = {
user: currentLoggedInUser
}
return<WrappedComponent {... this.props} {... newProps}/> } } }Copy the code
- Component instances are accessed through refs to invoke component-related methods
// WrappedComponent calls the ref callback during its initial rendering, passing in the component instance and invoking the component method in the proc methodfunction refsHOC(WrappedComponent) {
return class RefsHOC extends React.Component {
proc(wrappedComponentInstance) {
wrappedComponentInstance.method()
}
render() { // Object.asign(); Copy the values of all enumerable properties from one or more source objects to the target Object const props = object.assign ({}, this.props, {ref: this.proc.bind(this)})return<WrappedComponent {... props}/> } } }Copy the code
- Extract state, which can be extracted by passing props and callback functions
// Extract the input value and onChange methodsfunction ppHOC(WrappedComponent) {
return class PP extends React.Component {
state = {
name: ' '
}
onNameChange(event) {
this.setState({
name: event.target.value
})
}
render() {
const newProps = {
name: {
value: this.state.name,
onChange: this.onNameChange.bind(this)
}
}
return<WrappedComponent {... this.props} {... @pphoc class Example extends React.Component {newProps}/>}}/ /render() {// After using the ppHOC decorator, the component props has the name attribute added and the input becomes the controlled componentreturn <input name="name"{... this.props.name}/> } }Copy the code
- Wrap WrappedComponent with other elements for layout, styling, and more
function ppHOC(WrappedComponent) {
return class PP extends React.Component {
render() {
return (
<div style={{display: 'block'}}> <WrappedComponent {... this.props}/> </div> ) } } }Copy the code
Inheritance Inversion
- HOC controls the render output of the WrappedComponent and can hijack the render content inherited from the class, modify it, filter it, and return the new display
// Filter out ul elements in the original componentfunction hoc(ComponentClass) {
return class HOC extends ComponentClass {
render() { const elementTree = super.render(); elementTree.props.children = elementTree.props.children.filter((z) => z.type ! = ="ul")
return React.cloneElement(elementTree);
}
}
}
@hoc
export default class ComponentClass extends React.Component {
render() {
return (
<div>
<p style={{color: 'brown'}} >!!! < / p > < ul > < li > 1 < / li > < li > 2 < / li > < / ul > < / div >)}}Copy the code
- To manipulate state,HOC can manipulate the state of a WrappedComponent instance. But this breaks the state of the WrappedComponent, so to restrict HOC reading or adding state, add state in a separate namespace
export function IIHOC(WrappedComponent) {
return class II extends WrappedComponent {
render() {
return (
<div>
<p>Props</p> <pre>{JSON.stringify(this.props, null, 2)}</pre>
<p>State</p><pre>{JSON.stringify(this.state, null, 2)}</pre>
{
super.render()
}
</div>
)
}
}
}
Copy the code
- Conditions apply colours to a drawing
// Assuming this.props. LoggedIn is true, HOC will render the WrappedComponent completelyfunction iiHOC(WrappedComponent) {
return class ii extends WrappedComponent {
render() {
if (this.props.loggedIn) {
return super.render()
} else {
return null
}
}
}
}
Copy the code
- Resolve missing WrappedComponent names
// Components wrapped in HOC lose their original names, affecting development and debugging, Can be as HOC in WrappedComponent name prefix name const. The componentName = WrappedComponent displayName | | WrappedComponent. Name | |'Component';
static displayName = `withModal(${componentName}) `;Copy the code
The practical application
- Record the localStorage return value
Const withStorage = (key) => WrappedComponent => {const withStorage = (key) => WrappedComponent => {return class extends Component {
componentWillMount() {
let data = localStorage.getItem(key);
this.setState({data});
}
render() {
return<WrappedComponent data={this.state.data} {... this.props} /> } } } @withStorage('data')
class MyComponent2 extends Component {
render() {
return <div>{this.props.data}</div>
}
}
@withStorage('name')
class MyComponent3 extends Component {
render() {
return <div>{this.props.data}</div>
}
}
Copy the code
- In the project, re-open the Modal box every time and destroy the data in Modal every time to prevent data contamination
const modalHoc = (options) => WrappedComponent => {
const componentName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
return class ModalComponent extends Component {
static displayName = `withModal(${componentName}) `;render() {
const {visible, onCancel} = this.props;
let title;
if (typeof options === 'string') title = options;
if (typeof options === 'function') title = options;
if (typeof options === 'object') title = options.title;
if (typeof title === 'function') title = title(this.props);
return (
<Modal
destroyOnClose
width="60%"
bodyStyle={{padding: 0}}
footer={null}
{...options}
title={title}
onCancel={onCancel}
visible={visible}
>
<WrappedComponent {...this.props}/>
</Modal>
);
}
}
};
@modalHoc('You can pass in different types of headings.')
Copy the code
😊 reference links: the react. HTML. Cn/docs/who…
😊 just joined the nuggets community, welcome to put forward valuable suggestions, progress together!