着手寫個React高階組件

是什麼

簡稱HOC,全稱 High Order Component。作用是給react組件增減props屬性。

怎樣用

為何不先說怎樣寫?恩,由於你實在已用過了,舉個例子:

// App.js

import {connect} from 'react-redux';

class App extends React.Component {
  render() {}
}

export default connect()(App);

熟習不?redux的連接器。不過筆者有潔癖,喜好用裝潢器:

// App.js

import {connect} from 'react-redux';

@connect()
export class App extends React.Component {
  render() {}
}

最先寫

connect()()能夠看出,connect是一個函數,返回值是個react組件。這麼智慧,好信服本身啊。

雛形

// myHoc.js
import React from 'react';

export const myHoc = () => {
  return (Wrapped) => {
    class Hoc extends React.Component {
      render() {
        return <Wrapped {...this.props}>;
      }
    }
    
    return Hoc;
  };
};

是的,高階組件的雛形,就是函數里隱蔽了一個react組件,而參數Wrapped是什麼?就是下面被裝潢的組件:

// App.js

@myHoc()
export class App extends React.Component {
  render() {}
}

恩恩,表現形式和redux的connect如出一轍。
所以用了高階組件后,export出去的不再是你本身寫的App(Class),而是末了一個高階。

增添props屬性

好的啦,如今用myHoc給App組件加點料:

// myHoc.js
export const myHoc = () => {
  return (Wrapped) => {
    class Hoc extends React.Component {
      render() {
        return <Wrapped {...this.props} whoAmI="原罪">;
      }
    }
    
    return Hoc;
  };
};
// App.js

@myHoc()
export class App extends React.Component {
  render() {
    return <div>{this.props.whoAmI}</div>;
  }
}

寧神,如今瀏覽器里已把我的名字 原罪 打印出來了。

多個高階組件

是的,寫完一個hoc以後,你就會有寫第二個的需求,那就一升引呢:

// App.js

@myHoc()
@yourHoc()
@hisHoc()
@herHoc()
export class App extends React.Component {
  render() {
    return <div>{this.props.whoAmI}</div>;
  }
}

這就是筆者為啥要用裝潢器的緣由,簡約,看起來愜意,寫起來快,我們看一下另一種寫法:

class App extends React.Component {
  render() {}
}

export default myHoc()(yourHoc()(hisHoc()(herHoc()(App))));

本身體味,格式化一下吧:

class App extends React.Component {
  render() {}
}

let hoc;
hoc = herHoc()(App);
hoc = hisHoc()(hoc);
hoc = yourHoc()(hoc);
hoc = myHoc()(hoc);

export default hoc;

寫得累不?來,給你條毛巾擦擦汗

帶參數

對了,hoc能夠吸收參數,比方如許:

// App.js

@myHoc('原罪2號')
export class App extends React.Component {
  render() {
    return <div>{this.props.whoAmI}</div>;
  }
}

那高階組件怎樣接呢?

// myHoc.js

export const myHoc = (name) => {
  return (Wrapped) => {
    class Hoc extends React.Component {
      render() {
        return <Wrapped {...this.props} whoAmI={name}>;
      }
    }
    
    return Hoc;
  };
};

我把hoc吸收到的參數又返還給了App組件,那如今瀏覽器輸出的就是:原罪2號

不帶參數

如今,你能夠有一個斗膽勇敢的插法..哦不,主意,就是@myHoc背面能夠不加括號嗎?是哦,看前面幾個案例,都是@myHoc()。好的,看我的:

// myHoc.js

export const myHoc = (Wrapped) => {
  class Hoc extends React.Component {
    render() {
      return <Wrapped {...this.props} whoAmI="原罪">;
    }
  }
    
  return Hoc;
};
// App.js

@myHoc
export class App extends React.Component {
  render() {
    return <div>{this.props.whoAmI}</div>;
  }
}

仔細的看官看一下myHoc.js和帶參數的時刻有什麼區別。是的,少了一層回調。假如你的高階組件不須要帶參數,如許寫也是很ok的。

操控原組件

你能夠須要拿被裝潢的組件的state數據或許實行它的要領。那末須要豎立一個援用:

// myHoc.js

import React from 'react';

export const myHoc = () => {
  return (Wrapped) => {
    class Hoc extends React.Component {
      appRef = null;
      
      componentDidMount() {
        // 能夠對被myHoc裝潢的組件做羞羞的事變了,:)
        console.log(this.appRef);
      }
    
      render() {
        return <Wrapped {...this.props} ref={(app) => {this.appRef = app}} >;
      }
    }
    
    return Hoc;
  };
};

注重: 在多個高階組件裝潢同一個組件的情況下,此法並不見效。你拿到的ref是上一個高階組件的函數中暫時天生的組件。而且在大多數情況下,你並不知道某個組件會被多少個高階裝潢!

總結

當項目中多處用到某個邏輯要領,然則這個邏輯不能放到util里的時刻,HOC合適你。一個HOC最好只做一件事,如許保護輕易

    原文作者:原罪
    原文地址: https://segmentfault.com/a/1190000015361704
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞