React高階組件用法總結(jié)

@[toc]

高階組件

什么是高階組件

高階組件就是一個(gè) React 組件包裹著另外一個(gè) React 組件
其中“包裹”的概念刹淌,因?yàn)樗赡軙?huì)有以下兩種不同的含義之一:

  1. Props Proxy: HOC 對傳給 WrappedComponentporps進(jìn)行操作,
  2. Inheritance Inversion: HOC 繼承WrappedComponent察滑。
    Props Proxy
//Props Proxy 最簡實(shí)現(xiàn)
function ppHOC(WrappedComponent) {
    return class PP extends React.Component {
        render() {
            return <WrappedComponent {...this.props} />
        }
    }
}

使用 Props Proxy 可以做什么
? 操作 props
? 通過 Refs 訪問到組件實(shí)例
? 提取 state
? 用其他元素包裹WrappedComponent

1.操作 props

function ppHOC(WrappedComponent) {
    return class PP extends React.Component {
        render() {
            const newProps = {
                id: newId
            }
            return <WrappedComponent {...this.props} {...newProps} />
        }
    }
}

2.通過 Refs 訪問到組件實(shí)例

function refsHOC(WrappedComponent) {
    return class RefsHOC extends React.Component {
        proc(wrappedComponentInstance) {
            wrappedComponentInstance.method()
        }

        render() {
            const props = Object.assign({}, this.props, { ref: this.proc.bind(this) })
            return <WrappedComponent {...props} />
        }
    }
}

const refHoc = WrappedComponent => class extends Component {
    componentDidMount() {
        console.log(this.instanceComponent, 'instanceComponent');
    }
    render() {
        return (<WrappedComponent
            {...this.props}
            ref={instanceComponent => this.instanceComponent = instanceComponent}
        />);
    }
};

3.提取 state

function ppHOC(WrappedComponent) {
    return class PP extends React.Component {
        constructor(props) {
            super(props)
            this.state = {
                name: ''
            }

            this.onNameChange = this.onNameChange.bind(this)
        }
        onNameChange(event) {
            this.setState({
                name: event.target.value
            })
        }
        render() {
            const newProps = {
                name: {
                    value: this.state.name,
                    onChange: this.onNameChange
                }
            }
            return <WrappedComponent {...this.props} {...newProps} />
        }
    }
}
@ppHOC
class Example extends React.Component {
    render() {
        return <input name="name" {...this.props.name} />
    }
}

4.包裹WrappedComponent

function ppHOC(WrappedComponent) {
    return class PP extends React.Component {
        render() {
            return (
                <div style={{ display: 'block' }}>
                    <WrappedComponent {...this.props} />
                </div>
            )
        }
    }
}

Inheritance Inversion
Inheritance Inversion 最簡實(shí)現(xiàn)

function iiHOC(WrappedComponent) {
    return class Enhancer extends WrappedComponent {
        render() {
            return super.render()
        }
    }
}

調(diào)用順序
didmount→HOC didmount→will unmount→HOC will unmount

使用 Inheritance Inversion可以做什么

? 渲染劫持
? 操作 state

1.渲染挾持

? 有條件地渲染元素樹

const MyContainer = (WrappedComponent) => class extends WrappedComponent {
    render() {
        if (this.props.loggedIn) {
            return super.render();
        } else {
            return null;
        }
    }
}

? 讀取和修改由 render 輸出的 React 元素樹

const MyContainer = (WrappedComponent) => class extends WrappedComponent {
    render() {
        const elementsTree = super.render();
        let newProps = {};
        if (elementsTree && elementsTree.type === 'input') {
            newProps = { value: 'may the force be with you' };
        }
        const props = Object.assign({}, elementsTree.props, newProps);
        const newElementsTree = React.cloneElement(elementsTree, props, elementsTree.props.children);
        return newElementsTree;
    }
}

2.操作state

高階組件可以讀取、修改 WrappedComponent 實(shí)例中的 state修肠,如果需要的話贺辰,也可以 增加 state。但這樣做嵌施,可能會(huì)讓 WrappedComponent 組件內(nèi)部狀態(tài)變得一團(tuán)糟饲化。

 const MyContainer = (WrappedComponent) => class extends WrappedComponent {
    render() {
        return (
            <p>
                <p>Props</p>
                <pre>{JSON.stringify(this.props)}</pre>
                <p>State</p>
                <pre>{JSON.stringify(this.state)}</pre>
                {super.render()}
            </p>);
    }
}

裝飾器
高階組件可以看做是裝飾器模式(Decorator Pattern)在React的實(shí)現(xiàn)。即允許向一個(gè)現(xiàn)有的對象添加新的功能吗伤,同時(shí)又不改變其結(jié)構(gòu)吃靠,屬于包裝模式(Wrapper Pattern)的一種
ES6中添加了一個(gè)decorator的屬性,使用@符表示足淆,可以更精簡的書寫巢块。

function HOCFactoryFactory(...params) {
    // do something with params
    return function HOCFactory(WrappedComponent) {
        return class HOC extends React.Component {
            render() {
                return <WrappedComponent {...this.props} />
            }
        }
    }
}

HOCFactoryFactory(params)(WrappedComponent)
//或
@HOCFatoryFactory(params)
class WrappedComponent extends React.Component{}

該篇文章借鑒了沈老師的總結(jié)筆記,還有許多大佬的博客巧号,如果有涉及侵權(quán)的族奢,請聯(lián)系我刪除。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丹鸿,一起剝皮案震驚了整個(gè)濱河市越走,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌靠欢,老刑警劉巖廊敌,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異门怪,居然都是意外死亡骡澈,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門薪缆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秧廉,“玉大人伞广,你說我怎么就攤上這事√鄣纾” “怎么了嚼锄?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蔽豺。 經(jīng)常有香客問我区丑,道長,這世上最難降的妖魔是什么修陡? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任沧侥,我火速辦了婚禮,結(jié)果婚禮上魄鸦,老公的妹妹穿的比我還像新娘宴杀。我一直安慰自己,他們只是感情好拾因,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布旺罢。 她就那樣靜靜地躺著,像睡著了一般绢记。 火紅的嫁衣襯著肌膚如雪扁达。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天蠢熄,我揣著相機(jī)與錄音跪解,去河邊找鬼。 笑死签孔,一個(gè)胖子當(dāng)著我的面吹牛叉讥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播饥追,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼节吮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了判耕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤翘骂,失蹤者是張志新(化名)和其女友劉穎壁熄,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碳竟,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡草丧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了莹桅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昌执。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烛亦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出懂拾,到底是詐尸還是另有隱情煤禽,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布岖赋,位于F島的核電站檬果,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏唐断。R本人自食惡果不足惜选脊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望脸甘。 院中可真熱鬧恳啥,春花似錦、人聲如沸丹诀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忿墅。三九已至扁藕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間疚脐,已是汗流浹背亿柑。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棍弄,地道東北人望薄。 一個(gè)月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像呼畸,于是被迫代替她去往敵國和親痕支。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 在多個(gè)不同的組件中需要用到相同的功能蛮原,這個(gè)解決方法卧须,通常有Mixin和高階組件。Mixin方法例如: 但是由于Mi...
    小魚小蝦小海洋閱讀 815評論 0 3
  • 在目前的前端社區(qū)儒陨,『推崇組合花嘶,不推薦繼承(prefer composition than inheritance)...
    Wenliang閱讀 77,660評論 16 125
  • 如果一個(gè)函數(shù)操作其他函數(shù),即將其他函數(shù)作為參數(shù)或?qū)⒑瘮?shù)作為返回值蹦漠,將其稱為高階函數(shù)椭员。高階組件(high-order...
    yuzhiyi_宇閱讀 20,403評論 1 11
  • React進(jìn)階之高階組件 前言 本文代碼淺顯易懂,思想深入實(shí)用笛园。此屬于react進(jìn)階用法隘击,如果你還不了解react...
    流動(dòng)碼文閱讀 1,183評論 0 1
  • 函數(shù)式編程侍芝,對應(yīng)的是聲明式編程,聲明式編程的本質(zhì)的lambda驗(yàn)算(是一個(gè)匿名函數(shù)埋同,即沒有函數(shù)名的函數(shù)州叠。Lambd...
    不安分的三好份子閱讀 1,002評論 0 1