React-setState润匙、HOC、Portal簡(jiǎn)單介紹

1唉匾、setState(newState,callback)

React中可以通過修改state孕讳,通知React進(jìn)行Update的方法
callback用途,接收更新后的state,可以繼續(xù)操作

一般情況下 是一個(gè)異步方法
但是在定時(shí)器以及原生DOM事件會(huì)是一個(gè)同步方法

異步方法的好處
setState設(shè)計(jì)為異步厂财,可以顯著的提升性能油啤;
如果每次調(diào)用setState都進(jìn)行一次更新,那么意味著render函數(shù)會(huì)被頻繁調(diào)用蟀苛,界面重新渲染益咬,這樣效率是很低的;
最好的辦法應(yīng)該是獲取到多個(gè)更新帜平,之后進(jìn)行批量更新幽告;
如果同步更新了state,但是還沒有執(zhí)行render函數(shù)裆甩,那么state和props不能保持同步冗锁;
state和props不能保持一致性,會(huì)在開發(fā)中產(chǎn)生很多的問題嗤栓;

在調(diào)用setState后直接使用新的state是不建議的
this.setState({id:'123'});
console.log(this.state.id) // 這時(shí)候id不一定是 123

應(yīng)該寫成
this.setState({id:'123'},(state)=>{
console.log(state.id) // 這時(shí)候 id===123
})

異步變同步(不推薦)

class MyComponent extend React.Component{

  constructor(){
    this.state={
      id:'haha'
    }
  }

  componentDidMount(){
    document.getElelemtnById('btn').addEventListener('clcik',()=>{
      this.setState({id:'123'});
      console.log(this.state.id) // 這時(shí)候id是 123
    })
  }

updateWithsetTimeout = ()=>{
  setTimeOut(()=>{
    this.setState({id:'123'});
    console.log(this.state.id) // 這時(shí)候id是 123
  },0)
}

render(){
  return (
    <>
      <button onClick={this.updateWithsetTimeout}>setTimeOut</button>
      <button id="btn">js function </button>
    </>
  )
}
}

2冻河、受控組件

在React 中,可變狀態(tài)(mutable state)通常保存在組件的state 屬性中茉帅,并且只能通過使用setState()來更新叨叙。
我們將兩者結(jié)合起來,使React的state成為“唯一數(shù)據(jù)源”堪澎;
渲染表單的React 組件還控制著用戶輸入過程中表單發(fā)生的操作擂错;
被React 以這種方式控制取值的表單輸入元素就叫做“受控組件”;
由于在表單元素上設(shè)置了value屬性樱蛤,因此顯示的值將始終為this.state.value钮呀,這使得React 的state 成為唯一數(shù)據(jù)源。
由于handleUsernameChange在每次按鍵時(shí)都會(huì)執(zhí)行并更新React 的state昨凡,因此顯示的值將隨著用戶輸入而更新爽醋。

class FormComponent extends React.Component{
  constructor(){
    this.state = {
      inputValue:'',
    }
  }

  onChange = (e) =>{
    const value = e.target.value;
    this.setState({inputValue:value});
  }

  render(){
    return (
      <input type="text" value={this.state.inputValue} onChange={this.onChange} />
    )
  }
}

3、非受控組件

如果要使用非受控組件中的數(shù)據(jù)便脊,那么我們需要使用ref來從DOM節(jié)點(diǎn)中獲取表單數(shù)據(jù)
在非受控組件中通常使用defaultValue來設(shè)置默認(rèn)值

class FormComponent extends React.Component{

  constructor(){
    this.inputRef = React.createRef();
  }

  onBtnClick = () =>{
    console.log(
      `input - ${this.inputRef.current.value}`
    );
  }

  render(){
    return (
      <>
        <input defaultValue="haha" ref={this.inputRef} />
        <button onClick={this.onBtnClick}>確定</button>
      </>
    )
  }
}

4蚂四、高階組件

至少滿足以下條件之一:
接受一個(gè)或多個(gè)函數(shù)作為輸入;
輸出一個(gè)函數(shù)就轧;

高階組件的英文是Higher-Order Components证杭,簡(jiǎn)稱為HOC田度;
官方的定義:高階組件是參數(shù)為組件妒御,返回值為新組件的函數(shù);

我們可以進(jìn)行如下的解析:
首先镇饺,高階組件本身不是一個(gè)組件乎莉,而是一個(gè)函數(shù);
其次,這個(gè)函數(shù)的參數(shù)是一個(gè)組件惋啃,返回值也是一個(gè)組件哼鬓;

function higherOrderComponent(component){
  class Component extends React.Component{
    render (){
      {/* 需要將接收的props進(jìn)行向下傳遞 */}
      return <component {...this.props}/>
    }
  }
  Component.displayName = "EnhancedComponent";
  return Component;
}
const EnhancedComponent = higherOrderComponent(WarppedComponent);

應(yīng)用場(chǎng)景一:props 增強(qiáng)
1、不改變?cè)写a情況下边灭,擴(kuò)增props react-redux的connect就是這個(gè)作用
2异希、利用高階組件進(jìn)行Context共享(減少業(yè)務(wù)組件在使用時(shí)對(duì)Context.Consumer 編寫不友好的問題)

應(yīng)用場(chǎng)景二:渲染判斷鑒權(quán)
加一層判斷,控制組件是否渲染

應(yīng)用場(chǎng)景三:生命周期劫持
虛空增加的一層父組件绒瘦,可以在原需要組件進(jìn)行渲染的時(shí)候称簿,根具特定的生命周期進(jìn)行一些類似于 熱點(diǎn)、渲染時(shí)間惰帽、錯(cuò)誤邊界捕獲等記錄憨降。

HOC的意義

我們會(huì)發(fā)現(xiàn)利用高階組件可以針對(duì)某些React代碼進(jìn)行更加優(yōu)雅的處理。
其實(shí)早期的React有提供組件之間的一種復(fù)用方式是mixin该酗,目前已經(jīng)不再建議使用:
Mixin可能會(huì)相互依賴授药,相互耦合,不利于代碼維護(hù)
不同的Mixin中的方法可能會(huì)相互沖突pMixin非常多時(shí)呜魄,組件是可以感知到的悔叽,甚至還要為其做相關(guān)處理,這樣會(huì)給代碼造成滾雪球式的復(fù)雜性

當(dāng)然爵嗅,HOC也有自己的一些缺陷:

HOC需要在原組件上進(jìn)行包裹或者嵌套骄蝇,如果大量使用HOC,將會(huì)產(chǎn)生非常多的嵌套操骡,這讓調(diào)試變得非常困難九火;
HOC可以劫持props,在不遵守約定的情況下也可能造成沖突册招;

Hooks的出現(xiàn)岔激,是開創(chuàng)性的,它解決了很多React之前的存在的問題
比如this指向問題是掰、比如hoc的嵌套復(fù)雜度問題等等虑鼎;

5、Portals的使用

通常來講键痛,當(dāng)你從組件的render方法返回一個(gè)元素時(shí)炫彩,該元素將被掛載到DOM節(jié)點(diǎn)中離其最近的父節(jié)點(diǎn):
Portals提供了一種將子節(jié)點(diǎn)渲染到存在于父組件以外的 DOM 節(jié)點(diǎn)的方案
ReactDOM.createPortal(child, container)
第一個(gè)參數(shù)(child)是任何可渲染的React 子元素,例如一個(gè)元素絮短,字符串或fragment江兢;
第二個(gè)參數(shù)(container)是一個(gè)DOM元素;

即使child子元素被掛載到其他DOM結(jié)點(diǎn)下丁频,只是DOM級(jí)掛載杉允,但是在Fiber樹上邑贴,它仍屬于原Parent結(jié)點(diǎn)的子節(jié)點(diǎn)。

現(xiàn)象級(jí)掛載
  就是從HTML代碼結(jié)構(gòu)上可以看到是確實(shí)被挪移到目標(biāo)結(jié)點(diǎn)下
  目標(biāo)結(jié)點(diǎn)通過添加事件監(jiān)聽叔磷,也能捕獲child子元素對(duì)應(yīng)冒泡的事件
仍屬于Parent原結(jié)點(diǎn)
  1拢驾、仍然可以使用Context,不脫離作用域范圍。
  2改基、在父結(jié)點(diǎn)上添加的React事件(onClick)繁疤,在子節(jié)點(diǎn)上發(fā)生時(shí)事件時(shí),仍能被冒泡捕獲到秕狰。
  3嵌洼、但是通過elemnt.addEventListener 這種方式就不能再捕獲對(duì)應(yīng)事件!因?yàn)镈OM元素真的被移走了封恰!
    <Parent onClick>
      <Portal>
        <Button />
      </Portal>
    </Parent>

即使這里的Portal被移動(dòng)到其他DOM結(jié)點(diǎn)下麻养,當(dāng)點(diǎn)擊Button時(shí),仍能被Parent的onClick事件所捕獲

代碼地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末诺舔,一起剝皮案震驚了整個(gè)濱河市鳖昌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌低飒,老刑警劉巖许昨,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異褥赊,居然都是意外死亡糕档,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門拌喉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來速那,“玉大人,你說我怎么就攤上這事尿背《搜觯” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵田藐,是天一觀的道長(zhǎng)荔烧。 經(jīng)常有香客問我,道長(zhǎng)汽久,這世上最難降的妖魔是什么鹤竭? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮景醇,結(jié)果婚禮上臀稚,老公的妹妹穿的比我還像新娘。我一直安慰自己啡直,他們只是感情好烁涌,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布苍碟。 她就那樣靜靜地躺著酒觅,像睡著了一般撮执。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上舷丹,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天抒钱,我揣著相機(jī)與錄音,去河邊找鬼颜凯。 笑死谋币,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的症概。 我是一名探鬼主播蕾额,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼彼城!你這毒婦竟也來了诅蝶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤募壕,失蹤者是張志新(化名)和其女友劉穎调炬,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舱馅,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缰泡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了代嗤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片棘钞。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖干毅,靈堂內(nèi)的尸體忽然破棺而出武翎,到底是詐尸還是另有隱情,我是刑警寧澤溶锭,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布宝恶,位于F島的核電站,受9級(jí)特大地震影響趴捅,放射性物質(zhì)發(fā)生泄漏垫毙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望压汪。 院中可真熱鬧泰演,春花似錦、人聲如沸膀藐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)额各。三九已至国觉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間虾啦,已是汗流浹背麻诀。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留傲醉,地道東北人蝇闭。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像硬毕,于是被迫代替她去往敵國(guó)和親呻引。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359