根據reactJs官方文檔的定義,HOC如下:
簡要來講的話,是一種重複利用組件邏輯的技術,接受一個組件,並且返回一個組件。
就上上面的例子一樣,會接受WrappedComponent然後返回enhancedComponent.下面舉例子來講解。
1.創建一個按鈕組件,並且監聽點擊次數
import React, { Component, useState, useEffect } from "react";
class ClickCounter extends Component {
constructor() {
super();
this.state = {
count: 0
};
this.incrementCount = this.incrementCount.bind(this);
}
incrementCount() {
this.setState(preveState => {
return {
count: preveState.count + 1
};
});
}
render() {
let { count } = this.state;
return (
<div>
<button onClick={this.incrementCount}>Clicked {count} times</button>
</div>
);
}
}
export default ClickCounter;
以上按鈕組件我們創建了按鈕組件並且監聽了點擊事件,然後增加了被點擊的次數.
後來我們又接到了一個需求,是要做一個監聽hover次數的組件。
創建一個監聽Hover次數的組件
我們很快做出來了,其實我們做的過程中只是改了事件,其餘的從ClickCounter這裏複製粘貼了過來。
class HoverCounter extends Component {
constructor() {
super();
this.state = {
count: 0
};
this.incrementCount = this.incrementCount.bind(this);
}
incrementCount() {
this.setState(preveState => {
return {
count: preveState.count + 1
};
});
}
render() {
let { count } = this.state;
return (
<div>
<h2 onMouseOver={this.incrementCount}>Hovered {count} times</h2>
</div>
);
}
}
然後我們做完了以後,又來了一個需求,說要寫一個監聽input有多少次keypressed.這個時候我們想到的第一個辦法,就複製粘貼上面寫的兩個組件的方法,改一改事件監聽函數,但我們聰明起來了,我們想到寫一個父組件,然後把count和incrementCount方法通過props的方式傳下來到ClickCounter,HoverCounter組件.比如一下:
這樣可以解決問題,在我們這個場景可以解決問題,但如果是一下情況就不太行了 。
把邏輯代碼移到最上層的組件,不是一個好的解決方式。這個時候HOC閃亮登場了,它的作用就是在組件間分享重用的邏輯代碼,接受一個組件,並且返回一個增強的組件。
我們定義一個WithCounter組件,作爲HOC
import React, { Component, useState, useEffect } from "react";
const UpdatedComponent = OriginalComponent => {
class NewComponent extends Component {
render() {
return <OriginalComponent name="Abdulla" />;
}
}
return NewComponent;
};
export default UpdatedComponent;
可以看到我們實現了一個組件,這個組件接受名字叫originalComponent的組件,然後返回newComponent組件。
我們在這裏爲了演示在originalComponent那裏傳了一個props,爲name=“Abdulla”。
下面來看ClickCounter,HoverCounter組件有了什麼變化.
我們可以看到兩處有了變化,import和export那裏有了變化。然後可以看到我們通過this.props.name來使用了剛纔傳進來的props.
在HoverCounter組件也類似,可以看到起了作用.
把count和incrementCount邏輯放到HOC組件裏。
1.)我們首先把在ClickCounter和HoverCounter裏的count和incrementCount邏輯移出去。
2.)在WithCounter(HOC組件)裏寫count和incrementCount邏輯,然後通過props傳出去,就像我們傳name一樣。
3.)然後在ClickCounter和HoverCounter組件裏使用這個props.
最後展示一下這3個組件的代碼
ClickCounter組件:
import React, { Component, useState, useEffect } from "react";
import UpdatedComponent from "./WithCounter";
class ClickCounter extends Component {
constructor() {
super();
// this.state = {
// count: 0
// };
// this.incrementCount = this.incrementCount.bind(this);
}
// incrementCount() {
// this.setState(preveState => {
// return {
// count: preveState.count + 1
// };
// });
// }
render() {
// let { count } = this.state;
return (
<div>
<button onClick={this.props.incrementCount}>
{this.props.name} Clicked {this.props.count} times
</button>
</div>
);
}
}
export default UpdatedComponent(ClickCounter);
沒有刪掉count和incrementCount邏輯,只是註釋了,爲了展示的更好,顯示HOC組件的優越性。
HoverCounter組件如下:
import React, { Component, useState, useEffect } from "react";
import UpdatedComponent from "./WithCounter";
class HoverCounter extends Component {
constructor() {
super();
// this.state = {
// count: 0
// };
// this.incrementCount = this.incrementCount.bind(this);
}
// incrementCount() {
// this.setState(preveState => {
// return {
// count: preveState.count + 1
// };
// });
// }
render() {
// let { count } = this.state;
return (
<div>
<h2 onMouseOver={this.props.incrementCount}>
{this.props.name} Hovered {this.props.count} times
</h2>
</div>
);
}
}
export default UpdatedComponent(HoverCounter);
WithCounter組件如下:
import React, { Component, useState, useEffect } from "react";
const UpdatedComponent = OriginalComponent => {
class NewComponent extends Component {
constructor() {
super();
this.state = {
count: 0
};
this.incrementCount = this.incrementCount.bind(this);
}
incrementCount() {
this.setState(preveState => {
return {
count: preveState.count + 1
};
});
}
render() {
return (
<OriginalComponent
name="Abdulla"
count={this.state.count}
incrementCount={this.incrementCount}
/>
);
}
}
return NewComponent;
};
export default UpdatedComponent;
總結起來,HOC的作用是爲了精簡代碼,實現代碼的複用.