簡體   English   中英

將 HOC 重構為鈎子

[英]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補充了componentDidMountcomponenetDidUnmount方法 ( 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM