hooks

簡述

Hooks?

hooks 是 React v16.7.0-alpha 加入的新特性,可以在 class 外使用 state 以及其他 React 新特性欠橘。

優(yōu)點

  • 相比類來說焚刺,相似的邏輯不再分隔開联四,代碼更簡潔

useState

  1. 和類的對比

一個計數(shù)小例子(來自官網(wǎng)~)

類方法實現(xiàn):
import React from 'react';
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <>
        <div>You clicked {this.state.count} times</div>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>add</button>
        <button onClick={() => this.setState({ count: this.state.count - 1 })}>reduce</button>
      </>
    );
  }
}
export default Example
useState 實現(xiàn):
import React,{ useState } from 'react';
import  styles from './main.module.less';

function Example() {
  const [count,setCount] = useState(1);
  return (
    <>
    <div className={styles.container}>you clicked {count} times</div>
    <button onClick={()=>setCount(count+1)}>add</button>
    <button onClick={()=>setCount(count-1)}>reduce</button>
  </>
  );
}

export default Example;
  1. useState
const [count,setCount] = useState(1);
// useState 返回的是一對值逗宜,如下:
var countStateVariable = useState(1); 
var count = countStateVariable[0]; // 第一個元素
var setCount = countStateVariable[1]; // 第二個元素

// 使用的是js的"數(shù)組破壞",官方解釋使用[0]和[1]會有很大的迷惑性~

多個 state 怎么寫?我們可以使用多個 useState.

function Example() {
  const [count,setCount] = useState(1);
  const [age,setAge] = useState(10);
  const [fruit,setFriute] = useState('apple');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  
  return (
    <>
    <div className={styles.container}>you clicked {count} times</div>
    <button onClick={()=>setCount(count+1)}>add</button>
    <button onClick={()=>setCount(count-1)}>reduce</button>
  </>
  );
}

那么React是怎么記住"哪個狀態(tài)對應哪個 useState"? 答案就是依賴調(diào)用鉤子函數(shù)的順序鳄梅。所以存在了幾條規(guī)范

useEffect

useEffect 允許你在功能組件里面執(zhí)行副作用

  • 和類的對比
類方法實現(xiàn):
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      data:{},
    };
  }

  componentDidMount(){
    fetch('/api/xiaoyi/goodsList').then(res=>res.json()).then(data=>{
      console.log(data,'data')
      setState({data})
    })
    window.addEventListener('resize', this.getHeight);
  }
  
  componentDidUpdate(preProps){
    if(preProp.id!==this.props.id){
      fetch('/api/xiaoyi/goodsList').then(res=>res.json()).then(data=>{
        console.log(data,'data')
      })
    }
  }

   componentWillUnmount() {
    window.remoteEventListener('resize', this.getHeight);
  }
  
  render() {
    return (
      <>
        <div>You clicked {this.state.count} times</div>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>add</button>
        <button onClick={() => this.setState({ count: this.state.count - 1 })}>reduce</button>
      </>
    );
  }
}
export default Example
useEffect 實現(xiàn):
import React,{ useState, useEffect } from 'react';
import  styles from './main.module.less';

function Example(props) {
  const [count,setCount] = useState(1);
  useEffect(()=>{
    fetch('/api/xiaoyi/goodsList').then(res=>res.json()).then(data=>{
      console.log(data,'data')
    })
    window.addEventListener('resize', ()=>{console.log(111)});
    
    return () => {
      window.removeEventListener('resize', ()=>{console.log(111)});
        }
  },[props.id])
  return (
    <>
    <div className={styles.container}>you clicked {count} times</div>
    <button onClick={()=>setCount(count+1)}>add</button>
    <button onClick={()=>setCount(count-1)}>reduce</button>

  </>
  );
}

export default Example;

Hooks允許我們根據(jù)代碼所做的而不是生命周期方法名來分割代碼未檩。

useEffect 的參數(shù)是一個函數(shù)戴尸,組件每次渲染之后,都會調(diào)用這個函數(shù)參數(shù)冤狡,這樣就達到了 componentDidMount 和 componentDidUpdate 一樣的效果孙蒙。

useEffect 第一個參數(shù)返回的一個函數(shù)相當于清除該副作用,會在每次渲染執(zhí)行筒溃。

為什么不在組件銷毀的時候執(zhí)行马篮?<br /> 因為如果要銷毀的內(nèi)容中間發(fā)生改變,在銷毀的時候怜奖,銷毀的就是之前的內(nèi)容浑测,不是當前要銷毀的了,就會產(chǎn)生bug。

useEffect 的第二個參數(shù)迁央,代表重新渲染如果這個值未發(fā)生變化掷匠,就跳過渲染。

如果要運行一個 effect 并只清理一次(在裝載和卸載時)岖圈,可以將空數(shù)組([])作為第二個參數(shù)傳遞讹语。這告訴react,您的效果不依賴于來自props或state的任何值蜂科,因此它不需要重新運行顽决。這并不是一個特殊的情況——它直接來自于輸入數(shù)組的工作方式。

rules

使用 hooks 的規(guī)則
  • 不要在循環(huán)导匣,條件或嵌套函數(shù)內(nèi)使用鉤子函數(shù)才菠。相反,要在函數(shù)頂層使用鉤子贡定。
  • 不要在常規(guī)的js函數(shù)里面使用鉤子函數(shù)
  • 可以自定義的鉤子函數(shù)里面使用
    <a name="WluJO"></a>
react 提供了esLint插件 [eslint-plugin-react-hooks](https://www.npmjs.com/package/eslint-plugin-react-hooks) 來幫助我們執(zhí)行這些規(guī)則
  • npm install eslint-plugin-react-hooks@next
規(guī)則由來

由上面可知赋访,單個組件使用多個 State 或者 Effect 鉤子函數(shù)時候,React 依賴調(diào)用鉤子函數(shù)的順序記住相對應的狀態(tài)的缓待。所以當使用條件判斷時候:

// 打破了第一條規(guī)則
  if (name !== '') {
    useEffect(function persistForm() {
      localStorage.setItem('formData', name);
    });
  }

當?shù)谝淮蝦ender,name!==''為true的時候蚓耽,這個鉤子函數(shù)會執(zhí)行;當下一次為false的時候旋炒,渲染就會跳過這個鉤子函數(shù)步悠。此時鉤子的調(diào)用順序發(fā)生了改變。(加入這個鉤子函數(shù)之前和之后都存在其他鉤子函數(shù))

useState('loving')          
// useEffect(persistForm)  // 這個 hook 將會被跳過
useState('lili')        // 現(xiàn)在讀取是2国葬,但是之前是3贤徒,讀取這個狀態(tài)變量就會出錯。

react不知道第二次useState hook調(diào)用返回什么汇四。react預期此組件中的第二個hook調(diào)用與PersisteForm效果相對應接奈,就像在上一次呈現(xiàn)期間一樣,但它不再如此通孽。從那時起序宦,我們跳過的鉤子調(diào)用之后的每一個鉤子調(diào)用也會一個接一個地移動,從而導致錯誤背苦。

useEffect(function persistForm() {
    // ??不會打破第一條規(guī)則
    if (name !== '') {
      localStorage.setItem('formData', name);
    }
  });

參考文檔:https://www.reactjscn.com/docs/hooks-state.html

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末互捌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子行剂,更是在濱河造成了極大的恐慌秕噪,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件厚宰,死亡現(xiàn)場離奇詭異腌巾,居然都是意外死亡遂填,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門澈蝙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吓坚,“玉大人,你說我怎么就攤上這事灯荧〗富鳎” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵逗载,是天一觀的道長哆窿。 經(jīng)常有香客問我,道長撕贞,這世上最難降的妖魔是什么更耻? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮捏膨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘食侮。我一直安慰自己号涯,他們只是感情好,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布锯七。 她就那樣靜靜地躺著链快,像睡著了一般。 火紅的嫁衣襯著肌膚如雪眉尸。 梳的紋絲不亂的頭發(fā)上域蜗,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天,我揣著相機與錄音噪猾,去河邊找鬼霉祸。 笑死,一個胖子當著我的面吹牛袱蜡,可吹牛的內(nèi)容都是我干的丝蹭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼坪蚁,長吁一口氣:“原來是場噩夢啊……” “哼奔穿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起敏晤,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤贱田,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后嘴脾,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體男摧,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了彩倚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片筹我。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖帆离,靈堂內(nèi)的尸體忽然破棺而出蔬蕊,到底是詐尸還是另有隱情,我是刑警寧澤哥谷,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布岸夯,位于F島的核電站,受9級特大地震影響们妥,放射性物質(zhì)發(fā)生泄漏猜扮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一监婶、第九天 我趴在偏房一處隱蔽的房頂上張望旅赢。 院中可真熱鬧,春花似錦惑惶、人聲如沸煮盼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽僵控。三九已至,卻和暖如春鱼冀,著一層夾襖步出監(jiān)牢的瞬間报破,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工千绪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留充易,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓翘紊,卻偏偏與公主長得像蔽氨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子帆疟,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

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