助你徹底理解React高階組件(Higher-Order Components)

助你徹底理解React高階組件(Higher-Order Components)

原文地址:https://github.com/brickspert... (若是你以爲對你有幫助,請在github給個star~您的start是我不斷創做的動力!)
原文不斷更新,此處不維護。javascript

有時候人們很喜歡造一些名字很嚇人的名詞,讓人一聽這個名詞就以爲本身不可能學會,從而讓人望而卻步。可是其實這些名詞背後所表明的東西其實很簡單。來自React.js 小書css

高階組件定義

a higher-order component is a function that takes a component and returns a new component.html

翻譯:高階組件就是一個函數,且該函數接受一個組件做爲參數,並返回一個新的組件。java

理解了嗎?看了定義似懂非懂?繼續往下看。react

函數模擬高階組件

咱們經過普通函數來理解什麼是高階組件哦~git

  1. 最普通的方法,一個welcome,一個goodbye。兩個函數先從localStorage讀取了username,而後對username作了一些處理。github

function welcome() {
    let username = localStorage.getItem('username');
    console.log('welcome ' + username);
}

function goodbey() {
    let username = localStorage.getItem('username');
    console.log('goodbey ' + username);
}

welcome();
goodbey();
  1. 咱們發現兩個函數有一句代碼是同樣的,這叫冗餘唉。很差很差~(你能夠把那一句代碼理解成平時的一大堆代碼)redux

    咱們要寫一箇中間函數,讀取`username`,他來負責把`username`傳遞給兩個函數。
function welcome(username) {
    console.log('welcome ' + username);
}

function goodbey(username) {
    console.log('goodbey ' + username);
}

function wrapWithUsername(wrappedFunc) {
    let newFunc = () => {
        let username = localStorage.getItem('username');
        wrappedFunc(username);
    };
    return newFunc;
}

welcome = wrapWithUsername(welcome);
goodbey = wrapWithUsername(goodbey);

welcome();
welcome();

好了,咱們裏面的wrapWithUsername函數就是一個「高階函數」。
他作了什麼?他幫咱們處理了username,傳遞給目標函數。咱們調用最終的函數welcome的時候,根本不用關心username是怎麼來的。antd

咱們增長個用戶study函數。app

function study(username){
    console.log(username+' study');
}
study = wrapWithUsername(study);

study();

這裏你是否是理解了爲何說wrapWithUsername是高階函數?咱們只須要知道,用wrapWithUsername包裝咱們的study函數後,study函數第一個參數是username

咱們寫平時寫代碼的時候,不用關心wrapWithUsername內部是如何實現的。

高階組件

高階組件就是一個沒有反作用的純函數。

咱們把上一節的函數通通改爲react組件。

  1. 最普通的組件哦。

welcome函數轉爲react組件。

import React, {Component} from 'react'

class Welcome extends Component {
    constructor(props) {
        super(props);
        this.state = {
            username: ''
        }
    }

    componentWillMount() {
        let username = localStorage.getItem('username');
        this.setState({
            username: username
        })
    }

    render() {
        return (
            <div>welcome {this.state.username}</div>
        )
    }
}

export default Welcome;

goodbey函數轉爲react組件。

import React, {Component} from 'react'

class Goodbye extends Component {
    constructor(props) {
        super(props);
        this.state = {
            username: ''
        }
    }

    componentWillMount() {
        let username = localStorage.getItem('username');
        this.setState({
            username: username
        })
    }

    render() {
        return (
            <div>goodbye {this.state.username}</div>
        )
    }
}

export default Goodbye;
  1. 如今你是否是更能看到問題所在了?兩個組件大部分代碼都是重複的唉。

按照上一節wrapWithUsername函數的思路,咱們來寫一個高階組件(高階組件就是一個函數,且該函數接受一個組件做爲參數,並返回一個新的組件)。

import React, {Component} from 'react'

export default (WrappedComponent) => {
    class NewComponent extends Component {
        constructor() {
            super();
            this.state = {
                username: ''
            }
        }

        componentWillMount() {
            let username = localStorage.getItem('username');
            this.setState({
                username: username
            })
        }

        render() {
            return <WrappedComponent username={this.state.username}/>
        }
    }

    return NewComponent
}

這樣咱們就能簡化Welcome組件和Goodbye組件。

import React, {Component} from 'react';
import wrapWithUsername from 'wrapWithUsername';

class Welcome extends Component {

    render() {
        return (
            <div>welcome {this.props.username}</div>
        )
    }
}

Welcome = wrapWithUsername(Welcome);

export default Welcome;
import React, {Component} from 'react';
import wrapWithUsername from 'wrapWithUsername';

class Goodbye extends Component {

    render() {
        return (
            <div>goodbye {this.props.username}</div>
        )
    }
}

Goodbye = wrapWithUsername(Goodbye);

export default Goodbye;

看到沒有,高階組件就是把username經過props傳遞給目標組件了。目標組件只管從props裏面拿來用就行了。

到這裏位置,高階組件就講完了。你再返回去理解下定義,是否是豁然開朗~

你如今理解react-reduxconnect函數~

reduxstateaction建立函數,經過props注入給了Component
你在目標組件Component裏面能夠直接用this.props去調用redux stateaction建立函數了。

ConnectedComment = connect(mapStateToProps, mapDispatchToProps)(Component);

至關於這樣

// connect是一個返回函數的函數(就是個高階函數)
const enhance = connect(mapStateToProps, mapDispatchToProps);
// 返回的函數就是一個高階組件,該高階組件返回一個與Redux store
// 關聯起來的新組件
const ConnectedComment = enhance(Component);

antd的Form也是同樣的

const WrappedNormalLoginForm = Form.create()(NormalLoginForm);

參考地址:

  1. http://huziketang.com/books/r...

  2. https://react.bootcss.com/rea...

相關文章
相關標籤/搜索