React setState() 詳情

為什么使用 setState() 由蘑?setState() 會(huì)對(duì)一個(gè)組件的 state 對(duì)象安排一次更新尼酿。當(dāng) state 改變了裳擎,該組件就會(huì)重新渲染思币。開發(fā)中我們不能直接通過修改 state 當(dāng)中的值來讓界面發(fā)生更新羡微,因?yàn)樾薷牧?state 后希望的是 React 根據(jù)最新的 state 值來進(jìn)行更新界面惶我,但是這種方式 React 并不知道數(shù)據(jù)發(fā)生了變化,所以必須通過 setState() 來告訴 React 數(shù)據(jù)已經(jīng)發(fā)生了變化需要更新界面盯蝴。

一捧挺、setState 可能是異步更新

class App extends Component {
  constructor() {
    super();
    this.state = {
      number: 0
    }
  }
  render() {
    return (
      <div>
        <h2>{this.state.number}</h2>
        <button onClick={e => this.addText()}>+1</button>
      </div>
    )
  }
  addText() {
    this.setState({
      number: this.state.number + 1
    });
    console.log(this.state.number);   // 0
  }
}

當(dāng)調(diào)用 this.setState({ number: this.state.number + 1 }) 后所打印得到的值依舊為 0尿瞭。
獲取異步更新后的數(shù)據(jù):

class App extends Component {
  constructor() {
    super();
    this.state = {
      number: 0
    }
  }
  render() {
    return (
      <div>
        <h2>{this.state.number}</h2>
        <button onClick={e => this.addText()}>+1</button>
      </div>
    )
  }
  // 方式二:通過聲明周期函數(shù)獲取異步更新的值
  componentDidUpdate() {
    console.log(this.state.number); // 1
  }
  addText() {
    this.setState({
      number: this.state.number + 1
    }, () => {  // 方式一:通過 setState 的回調(diào)函數(shù)獲取異步更新的值
      console.log(this.state.number);   // 1
    });
  }
}

二筷厘、setState 可能是同步更新

  • 當(dāng) setState() 方法在 setTimeout() 中執(zhí)行:
class App extends Component {
  constructor() {
    super();
    this.state = {
      number: 0
    }
  }
  render() {
    return (
      <div>
        <h2>{this.state.number}</h2>
        <button onClick={e => this.addText()}>+1</button>
      </div>
    )
  }
  addText() {
    setTimeout(() => {
      this.setState({
        number: this.state.number + 1
      });
      console.log(this.state.number); // 1
    }, 0);
  }
}
  • 當(dāng) setState() 方法在原生 DOM 事件中執(zhí)行:
class App extends Component {
  constructor() {
    super();
    this.state = {
      number: 0
    }
  }
  componentDidMount() {
    // 原生點(diǎn)擊事件
    const btnEl = document.getElementById('btn');
    btnEl.addEventListener('click', () => {
      this.setState({
        number: this.state.number + 1
      });
      console.log(this.state.number); // 1
    })
  }
  render() {
    return (
      <div>
        <h2>{this.state.number}</h2>
        <button id='btn'>+1</button>
      </div>
    )
  }
}

一般情況下酥艳,setState() 方法在組件生命周期或 React 合成事件中是異步更新的摊溶;在 setTimeout() 或者原生 DOM 事件中是同步的。

三充石、setState 數(shù)據(jù)的合并

// this.state 當(dāng)中有兩個(gè)屬性
constructor() {
    super();
    this.state = {
      number: 0,
      name: 'zhangsan'
    }
}
/* --------------- */
// 更新 state
this.setState({
     number: 10
});

當(dāng) constructor 中的 this.state 有多個(gè)屬性時(shí)莫换,調(diào)用 this.setState() 方法更新其中一條 number 屬性后,不會(huì)將之前的 name 屬性覆蓋骤铃,而是單獨(dú)修改 number 屬性拉岁,等同于:
Object.assign({}, this.state, { number: 10 })

四、setState 本身的合并

class App extends Component {
  constructor() {
    super();
    this.state = {
      number: 0
    }
  }
  render() {
    return (
      <div>
        <h2>{this.state.number}</h2>
        <button onClick={e => this.addText()}>+1</button>
      </div>
    )
  }

  addText() {
    // setState 本身被合并
    // this.setState({
    //   number: this.state.number + 1
    // });
    // this.setState({
    //   number: this.state.number + 1
    // });
    // this.setState({
    //   number: this.state.number + 1
    // });
    /* 最終結(jié)果還是 1 */

    // setState 合并時(shí)進(jìn)行累加
    this.setState((prevState, props) => {
      return {
        number: prevState.number + 1
      }
    })
    this.setState((prevState, props) => {
      return {
        number: prevState.number + 1
      }
    })
    this.setState((prevState, props) => {
      return {
        number: prevState.number + 1
      }
    })
    /* 最終結(jié)果為 3 */
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惰爬,一起剝皮案震驚了整個(gè)濱河市喊暖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撕瞧,老刑警劉巖陵叽,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件页畦,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)记焊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門恩尾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翰意,“玉大人,你說我怎么就攤上這事】湍辏” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵耍共,是天一觀的道長枫弟。 經(jīng)常有香客問我伊履,道長群凶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任当窗,我火速辦了婚禮元咙,結(jié)果婚禮上庶香,老公的妹妹穿的比我還像新娘倘零。我一直安慰自己,他們只是感情好袖瞻,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著牺堰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪斧抱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天废膘,我揣著相機(jī)與錄音丐黄,去河邊找鬼。 笑死桂对,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播爬范,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼杜顺,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼搭儒!你這毒婦竟也來了馁菜?” 一聲冷哼從身側(cè)響起智嚷,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤猜嘱,失蹤者是張志新(化名)和其女友劉穎腕让,沒想到半個(gè)月后觉鼻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體萨惑,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刻盐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乙墙。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡肛走,死狀恐怖梢褐,靈堂內(nèi)的尸體忽然破棺而出组底,到底是詐尸還是另有隱情筐骇,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布江滨,位于F島的核電站铛纬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏唬滑。R本人自食惡果不足惜告唆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望间雀。 院中可真熱鬧,春花似錦镊屎、人聲如沸惹挟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽连锯。三九已至,卻和暖如春用狱,著一層夾襖步出監(jiān)牢的瞬間运怖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工夏伊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留摇展,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓溺忧,卻偏偏與公主長得像咏连,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鲁森,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

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