[英]Refactor HOC as hook
在我花在 react 和幾篇文章上的時間里,我問自己如何將 HOC 重構為鈎子,以及它是否有用以及為什么,
這是一個重構的小組件
function withSpacing(Component) {
const WrappedWithSpacing = ({
pv, ph, pt, pb, pl, pr, style, ...props
}) => {
const styleWithSpacing = {};
const spacing = layout.padding;
const paddingTop = pt || pv;
const paddingBottom = pb || pv;
const paddingRight = pr || ph;
const paddingLeft = pl || ph;
if(paddingTop > 0) styleWithSpacing.paddingTop = paddingTop * spacing;
if(paddingBottom > 0) styleWithSpacing.paddingBottom = paddingBottom * spacing;
if(paddingLeft > 0) styleWithSpacing.paddingLeft = paddingLeft * spacing;
if(paddingRight > 0) styleWithSpacing.paddingRight = paddingRight * spacing;
return <Component style={{...style, ...styleWithSpacing}} {...props} />
}
WrappedWithSpacing.propTypes = {
pv: PropTypes.number,
ph: PropTypes.number,
pt: PropTypes.number,
pb: PropTypes.number,
pl: PropTypes.number,
pr: PropTypes.number,
style: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
}
WrappedWithSpacing.defaultProps = {
pv: 0,
ph: 0,
pt: 0,
pb: 0,
pr: 0,
pl: 0,
}
return WrappedWithSpacing;
}
export default withSpacing;
根據官方文檔:
Hooks 會取代渲染道具和高階組件嗎?
通常,渲染道具和高階組件僅渲染一個子組件。 我們認為 Hooks 是一種更簡單的方法來服務於這個用例。 這兩種模式仍有一席之地(例如,虛擬滾動組件可能有一個 renderItem 道具,或者可視化容器組件可能有自己的 DOM 結構)。 但在大多數情況下,Hooks 就足夠了,可以幫助減少樹中的嵌套。
我使用這個 HOC 只是為了向組件添加一些預定義的空間。
將它重構為鈎子會更好,你能解釋一下為什么嗎?
如果是,那么將其重構為 hook 的最佳方法是什么?
TDLR; 因為您的 HOC 沒有任何狀態或訂閱,所以沒有正當理由使用鈎子重構您的組件。
React Hooks 引入了幾個新特性來作為 React Hooks 的補充,以補充其基於類的對應物。 useState
補充this.state
( docs ) 作為在渲染之間存儲狀態的功能方式。 useEffect
補充了componentDidMount
和componenetDidUnmount
方法 ( docs ),它提供了一種方法來執行功能性反應組件的設置和拆除。
如果您從文檔中獲取了這樣的 HOC:
// This function takes a component...
function withSubscription(WrappedComponent, selectData) {
// ...and returns another component...
return class extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
data: selectData(DataSource, props)
};
}
componentDidMount() {
// ... that takes care of the subscription...
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
this.setState({
data: selectData(DataSource, this.props)
});
}
render() {
// ... and renders the wrapped component with the fresh data!
// Notice that we pass through any additional props
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
}
並將其轉換為功能組件,您可能會得到如下結果:
function withSubscription(WrappedComponent, selectData) {
return function WrappedComponent (props) {
const [myData, setMyData] = useState(null);
useEffect(() => {
const handleMyDataChange = newData => {
setMyData(newData);
}
DataSource.addChangeListener(handleMyDataChange);
return function cleanup() {
DataSource.removeChangeListener(handleMyDataChange);
};
});
return <WrappedComponent data={data} {...this.props} />;
}
您的填充和間距在每次渲染時都會重新生成。 由於您的問題中的代碼在渲染之間沒有任何持久性,因此嘗試將其重構為實現 React Hooks 的組件沒有多大意義。 React Hooks 更適合將基於類的 React 組件轉換為功能性的 React 組件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.