React快速上手6-Context、高階組件和Hooks

Context API

react組件中經(jīng)常會遇到這樣一種情況羡微,由于組件嵌套層數(shù)過多導(dǎo)致state管理復(fù)雜傻唾,props傳遞不方便投慈,這個時候你可以使用redux之流來進(jìn)行狀態(tài)管理,但是如果只是個別state難以管理冠骄,redux可能有點(diǎn)殺雞用牛刀了伪煤,這時你可以考慮試一下context API。
在react官網(wǎng)文檔中是這樣來介紹context的:

Context provides a way to pass data through the component tree without having to pass props down manually at every level.(Context提供了一種通過組件樹傳遞數(shù)據(jù)的方法凛辣,而無需在每一級手動傳遞props抱既。)
下面我們一步一步來看一下如何去使用context

  1. 我們通過React.createContext()創(chuàng)建一個context對象:
const { Provider, Consumer } = React.createContext()
  1. 然后創(chuàng)建一個返回Provider組件的包裝器組件,并添加要從中訪問上下文的所有組件作為子組件:
class Container extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 0
    }
  }
  render() {
    return (
      <Provider value={{ 
          state: this.state 
      }}>
        {this.props.children}
      </Provider>
    )
  }
}

class Calculator extends React.Component {
  render() {
    return (
      <Container>
        <Button />
      </Container>
    )
  }
}

Container組件將是一個全局的Provider扁誓,您還可以創(chuàng)建較小的context防泵。

  1. 在Provider中包含的組件內(nèi)部,使用Consumer組件來使用context:
class Button extends React.Component {
  render() {
    return (
      <Consumer>
        {context => <button>{context.state.count}</button>
      </Consumer>
    )
  }
}

4.您還可以將函數(shù)作為傳遞值給Provider蝗敢,而Consumer可以使用這些函數(shù)來更新context的state:

class Container extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 0
    }
  }
  render() {
    return (
      <Provider value={{ 
          state: this.state捷泞,
          addHandle : ()=>{this.setState({count: this.state.count+1})}
      }}>
        {this.props.children}
      </Provider>
    )
  }
}
/**...**/
<Consumer>
  {(context) => (
    <button onClick={context.addHandle}>
      {context.state.count}
    </button>
  )}
</Consumer>

這樣一來,你就可以很好的解決了多層組件套用的問題前普。
關(guān)于context更多的用法肚邢,可以參考react官方文檔

高階組件基礎(chǔ)應(yīng)用(HOC)

高階組件在react中是一個非常有用的概念,它有點(diǎn)類似于javascript中的高級函數(shù),比如說Array.map()骡湖,接受函數(shù)作為一個參數(shù)贱纠,在react中,如果一個組件接受一個組件然后返回一個組件响蕴,那么這個組件就可以被稱為高階組件谆焊。
一般來說,高階組件經(jīng)常用來創(chuàng)建高可復(fù)用性的代碼浦夷,舉個例子辖试,我們可以給一個組件去給一個組件添加一些方法或者屬性,或者是一個redux store劈狐。
下面將給出一個最基礎(chǔ)的例子:

const withColor = (Element) =>{
    return (
        (props) => <Element {...props} color="red" />
    )
}

withColor是一個組件罐孝,它傳遞一個組件作為參數(shù),返回一個組件并給這個組件設(shè)置了color為'red'肥缔。
接下來我們使用withColor這個高級組件:

const Button = () => {
  return <button>test</button>
}
const ColoredButton = withColor(Button)

最后我們在渲染出ColoredButton組件:

function App() {
  return (
    <div className="App">
      <h1>Hello</h1>
      <ColoredButton />
    </div>
  )
}

這只是一個最基礎(chǔ)的高階組件的示例莲兢,但希望在將這些概念應(yīng)用于更復(fù)雜的場景之前,能夠?qū)斫飧唠A組件的要點(diǎn)有所幫助续膳。

Hooks

Hooks是在React 16.7中引入的新特性改艇,它的作用是能夠讓我們在函數(shù)定義的組件中使用state和生命周期事件,使得函數(shù)組件有一個處理事件的好方法坟岔。

1. 獲取state

我們使用useState()API谒兄,創(chuàng)建一個新的state變量,并且可以修改它社付。 useState()接受state項(xiàng)的初始值承疲,并返回一個包含state變量的數(shù)組,以及您調(diào)用以更改狀態(tài)的方法瘦穆。 由于它返回一個數(shù)組纪隙,我們使用數(shù)組解構(gòu)來訪問每個單獨(dú)的項(xiàng)赊豌,如下所示:

import React, { useState } from 'react'

const Counter = () => {
  const [count, setCount] = useState(0)
  return (
    <div>
      <p>總數(shù):{count}</p>
      <button onClick={() => setCount(count + 1)}>點(diǎn)擊+1</button>
    </div>
  )
}

ReactDOM.render(<Counter />, document.getElementById('app'))

你可以盡可能的調(diào)用useState()扛或,來創(chuàng)建你所需要的state變量,而你只需保證在組件的頂層(不在if或任何其他塊中)調(diào)用它就ok了碘饼。

2.使用生命周期函數(shù)

在類組件中熙兔,您擁有componentDidMount,componentWillUnmount和componentDidUpdate等生命周期函數(shù)艾恼,這些函數(shù)提供了從變量初始化到API調(diào)用等等的用例住涉。
在函數(shù)式組件中,Hooks提供useEffect()API钠绍,它接受函數(shù)作為它的參數(shù)舆声,在首次渲染組件時運(yùn)行,在后面每次重新渲染或組件更新時也會運(yùn)行。React首先會更新DOM媳握,然后調(diào)用傳遞給useEffect()的函數(shù)碱屁,與舊的componentDidMount和componentDidUpdate有點(diǎn)類似,但是又有所不同蛾找,因?yàn)檫@些操作都不會阻止UI渲染娩脾,即使是阻塞了代碼,這使我們的APP感覺上更快了打毛。

import React,{ useEffect, useState }from 'react'

const CounterWithNameAndSideEffect = () => {
  const [count, setCount] = useState(0)
  const [name, setName] = useState('Flavio')

  useEffect(() => {
    console.log(`Hi ${name} you clicked ${count} times`)
  })

  return (
    <div>
      <p>
        Hi {name} you clicked {count} times
      </p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
      <button onClick={() => setName(name === 'Flavio' ? 'Roger' : 'Flavio')}>
        Change name
      </button>
    </div>
  )
}

ReactDOM.render(
  <CounterWithNameAndSideEffect />,
  document.getElementById('app')
)

如果我們使用useEffect()有點(diǎn)類似于componentWillUnmount的功能應(yīng)該怎么操作呢柿赊?我們可以在傳遞給useEffect()的函數(shù)里再返回一個函數(shù):

useEffect(() => {
  console.log(`Hi ${name} you clicked ${count} times`)
  return () => {
    console.log(`Unmounted`)
  }
})

在每次重新渲染/更新時,useEffect()函數(shù)都會執(zhí)行幻枉,這時我們可以給useEffect添加第二個參數(shù)來告訴React跳過運(yùn)行碰声,這個參數(shù)是一個包含了需要監(jiān)視的state變量的數(shù)組,如果數(shù)組中的其中一項(xiàng)發(fā)生改變熬甫,react將只會重新執(zhí)行useEffect:

useEffect(
  () => {
    console.log(`Hi ${name} you clicked ${count} times`)
  },
  [name, count]
)

有點(diǎn)類似的是奥邮,你也可以傳遞一個空數(shù)組,這樣的話罗珍,React只執(zhí)行一次useEffect(在掛載時):

useEffect(() => {
  console.log(`Component mounted`)
}, [])

3. Hooks規(guī)則

以上是Hooks的最基本的用法洽腺,理解這些,基本能應(yīng)付大部分的應(yīng)用場景覆旱,在react官方文檔中蘸朋,定義了Hooks的兩條規(guī)則:

  • 在最頂層調(diào)用Hooks
    不要在循環(huán),條件或嵌套函數(shù)中調(diào)用Hook扣唱。 相反藕坯,始終在React函數(shù)的頂層使用Hooks。 通過遵循此規(guī)則噪沙,您可以確保每次組件呈現(xiàn)時都以相同的順序調(diào)用Hook炼彪。 這就是允許React在多個useState和useEffect調(diào)用之間正確保留Hook狀態(tài)的原因。
  • 只在react 函數(shù)式組件中調(diào)用Hooks
    不要在普通js函數(shù)中調(diào)用Hooks正歼,你只能在react函數(shù)式組件中調(diào)用Hooks或者在普通的Hooks中調(diào)用Hooks辐马。

更多詳情可以參考Hooks的官方文檔

持續(xù)更新中

上一篇:React快速上手5-react中的事件和生命周期函數(shù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市局义,隨后出現(xiàn)的幾起案子喜爷,更是在濱河造成了極大的恐慌,老刑警劉巖萄唇,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件檩帐,死亡現(xiàn)場離奇詭異,居然都是意外死亡另萤,警方通過查閱死者的電腦和手機(jī)湃密,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泛源,你說我怎么就攤上這事揍障。” “怎么了俩由?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵毒嫡,是天一觀的道長。 經(jīng)常有香客問我幻梯,道長兜畸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任碘梢,我火速辦了婚禮咬摇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘煞躬。我一直安慰自己肛鹏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布恩沛。 她就那樣靜靜地躺著在扰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪雷客。 梳的紋絲不亂的頭發(fā)上芒珠,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天,我揣著相機(jī)與錄音搅裙,去河邊找鬼皱卓。 笑死,一個胖子當(dāng)著我的面吹牛部逮,可吹牛的內(nèi)容都是我干的娜汁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼兄朋,長吁一口氣:“原來是場噩夢啊……” “哼掐禁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蜈漓,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤穆桂,失蹤者是張志新(化名)和其女友劉穎宫盔,沒想到半個月后融虽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡灼芭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年有额,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡巍佑,死狀恐怖茴迁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情萤衰,我是刑警寧澤堕义,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站脆栋,受9級特大地震影響倦卖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜椿争,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一怕膛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧秦踪,春花似錦褐捻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至景馁,卻和暖如春边苹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背裁僧。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工个束, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人聊疲。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓茬底,卻偏偏與公主長得像,于是被迫代替她去往敵國和親获洲。 傳聞我的和親對象是個殘疾皇子阱表,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評論 2 359

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