React HOC

在React官網(wǎng)文檔學(xué)習(xí)React HOC背桐,整個(gè)看了一遍還是云里霧里的募书,于是按照官網(wǎng)文檔,自己動(dòng)手實(shí)踐一下捶障。官網(wǎng)地址:React 高階組件

定義:高階組件就是一個(gè)函數(shù)是鬼,且該函數(shù)接受一個(gè)組件作為參數(shù)猿棉,并返回一個(gè)新的組件

使用高階組件(HOC)解決交叉問題

假設(shè)有兩個(gè)組件,CommentList組件從外部數(shù)據(jù)源訂閱數(shù)據(jù)并渲染評論列表屑咳,BlogPost組件是一個(gè)訂閱單個(gè)博客文章的組件萨赁,該組件遵循類似的模式,即在componentDidMount中添加事件處理函數(shù)訂閱數(shù)據(jù)兆龙,在componentWillUnmount中清除事件處理函數(shù)杖爽,兩個(gè)組件的事件處理函數(shù)內(nèi)容相同。兩個(gè)組件的區(qū)別在于:從數(shù)據(jù)源訂閱的數(shù)據(jù)不同紫皇,并且渲染格式不同慰安。(代碼見React官網(wǎng))
由此,可以將兩個(gè)組件中相同的邏輯部分提取到一個(gè)高階組件聪铺,該高階組件能夠創(chuàng)建類似 CommonList 和 BlogPost 從數(shù)據(jù)源訂閱數(shù)據(jù)的組件 化焕。該組件接受一個(gè)子組件作為其中的一個(gè)參數(shù),并從數(shù)據(jù)源訂閱數(shù)據(jù)作為props屬性傳入子組件铃剔。該高階組件命名為WithSubscription撒桨。

import DataSource from '../DataSource'
let withSubscription = (WrappedComponent, selectData) => {
    // ……返回另一個(gè)新組件……
    return class extends React.Component {
        constructor(props) {
            super(props);
            this.handleChange = this.handleChange.bind(this);
            this.state = {
                data: selectData(DataSource, props)
            };
        }

        componentDidMount() {
            // ……注意訂閱數(shù)據(jù)……
            DataSource.addChangeListener(this.handleChange);
        }

        componentWillUnmount() {
            DataSource.removeChangeListener(this.handleChange);
        }

        handleChange() {
            this.setState({
                data: selectData(DataSource, this.props)
            });
        }
        render() {
            // ……使用最新的數(shù)據(jù)渲染組件
            // 注意此處將已有的props屬性傳遞給原組件
            const style = {
                'marginBottom':'30px'
            }
            return(
                <div style={style}>
                    <div>This is a HOC Component...</div>
                    <WrappedComponent data={this.state.data} {...this.props} />
                </div>
            );
        }
    };
}
export default withSubscription;

高階組件既不會(huì)修改原組件,也不會(huì)使用繼承復(fù)制原組件的行為键兜。相反凤类,高階組件是通過將原組件包裹(wrapping)在容器組件(container component)里面的方式來組合(composes) 使用原組件。高階組件就是一個(gè)沒有副作用的純函數(shù)普气。
高階組件接收容器組件的所有props屬性以及一個(gè)新的 data屬性谜疤,并將從數(shù)據(jù)源訂閱的數(shù)據(jù)用 data 屬性渲染輸出內(nèi)容。高階組件并不關(guān)心數(shù)據(jù)是如何以及為什么被使用,而被包裹組件也不關(guān)心數(shù)據(jù)來自何處夷磕。

高階組件使用

./pages/index.js
import React from 'react'
import HOCList from '../components/HOCList';
import CommentList from '../components/CommentList';
import BlogPost from '../components/BlogPost';
import withSubscription from '../components/WithSubscription/index'

const CommentListWithSubscription = withSubscription(
    CommentList,
    (DataSource) => DataSource.getComments()
);

const BlogPostWithSubscription = withSubscription(
    BlogPost,
    (DataSource, props) => DataSource.getBlogPost(props.id)
);
export default class extends React.Component {
    constructor(props) {
        super(props);
    }
    componentDidMount() {
    }

    render() {
        const style = {
            width:'100%',
            'text-align': 'center',
            title:{
                color:'red'
            }
        }
        return (
            <div style={style}>
                <h1 style={style.title}>hello hoc</h1>
                <CommentListWithSubscription />
                <BlogPostWithSubscription />
            </div>
        );
    }
}

CommentListWithSubscription的第一個(gè)參數(shù)是包裹組件(wrapped component)履肃,第二個(gè)參數(shù)會(huì)從 DataSource和當(dāng)前props即高階組件的props屬性中檢索需要的數(shù)據(jù)。
當(dāng) CommentListWithSubscription 和 BlogPostWithSubscription 渲染時(shí), 會(huì)向CommentList 和 BlogPost 傳遞一個(gè) data props屬性坐桩,該 data屬性的數(shù)據(jù)包含了從 DataSource 檢索的最新數(shù)據(jù)尺棋。

官網(wǎng)的示例代碼不完全,為了更好地看到運(yùn)行結(jié)果撕攒,對代碼做一些修改:

  • 另外創(chuàng)建數(shù)據(jù)源DataSource:
./components/DataSource.js
let DataSource = {
    getComments: () => {
        return [
            'comment1', 'comment2', 'comment3'
        ]
    },
    getBlogPost: () => {
        return 'BlogPost Contents';
    },
    addChangeListener: () => { console.log('addChangeListener') },
    removeChangeListener: () => { console.log('removeChangeListener') },
}
export default DataSource;
  • 兩個(gè)被包裹組件只負(fù)責(zé)對數(shù)據(jù)源的展示:
//.components/BlogPost/index.js
import React from 'react'
import { Input,Button } from 'antd'

const { TextArea } = Input;
export default class extends React.Component {
  render() {
      return (
          <div>
              <TextArea value={this.props.data} />
          </div>
      );
  }
}
//.components/BlogPCommentListst/index.js
import React from 'react'

export default class extends React.Component {
    render() {
        return (
            <div>
                {this.props.data.map((value) => (
                    <div comment={value} key={value} >{value}</div>
                ))}
            </div>
        );
    }
}

運(yùn)行結(jié)果:http://localhost:3000/

localhost:3000

完整源碼地址:https://github.com/wuhuaranran/myHOC

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末陡鹃,一起剝皮案震驚了整個(gè)濱河市烘浦,隨后出現(xiàn)的幾起案子抖坪,更是在濱河造成了極大的恐慌,老刑警劉巖闷叉,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件擦俐,死亡現(xiàn)場離奇詭異,居然都是意外死亡握侧,警方通過查閱死者的電腦和手機(jī)蚯瞧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來品擎,“玉大人埋合,你說我怎么就攤上這事√汛” “怎么了甚颂?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長秀菱。 經(jīng)常有香客問我振诬,道長,這世上最難降的妖魔是什么衍菱? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任赶么,我火速辦了婚禮,結(jié)果婚禮上脊串,老公的妹妹穿的比我還像新娘辫呻。我一直安慰自己,他們只是感情好琼锋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布印屁。 她就那樣靜靜地躺著,像睡著了一般斩例。 火紅的嫁衣襯著肌膚如雪雄人。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機(jī)與錄音础钠,去河邊找鬼恰力。 笑死,一個(gè)胖子當(dāng)著我的面吹牛旗吁,可吹牛的內(nèi)容都是我干的踩萎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼很钓,長吁一口氣:“原來是場噩夢啊……” “哼香府!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起码倦,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤企孩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后袁稽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體勿璃,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年推汽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了补疑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡歹撒,死狀恐怖莲组,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情暖夭,我是刑警寧澤锹杈,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站鳞尔,受9級特大地震影響嬉橙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寥假,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一市框、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧糕韧,春花似錦枫振、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至雀扶,卻和暖如春肆汹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背予权。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工昂勉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人扫腺。 一個(gè)月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓岗照,卻偏偏與公主長得像,于是被迫代替她去往敵國和親笆环。 傳聞我的和親對象是個(gè)殘疾皇子攒至,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354

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