[React Native] React 中的狀態(tài)(State)

目錄

  • 1.state 屬性
    • 1.1 state屬性的介紹
    • 1.2 state 的使用
  • 2.setState() 方法
    • 2.1 第一個參數(shù):updater 函數(shù)
    • 2.2 第二個參數(shù):callback
  • 3.正確操作 state
    • 3.1 不要使用 this.state 來直接修改 state
    • 3.2 狀態(tài)更新可能是異步的
    • 3.3 狀態(tài)更新是一個合并的過程
  • 4.單向數(shù)據(jù)流
  • 5.完整示例代碼

state 屬性是 React 組件用來更新數(shù)據(jù)的核心特性,也是我們平時見得最多的屬性之一,那么你對 state 又了解多少呢李根?

1. state 屬性

1.1 state屬性的介紹

我們使用兩種數(shù)據(jù)來控制一個組件:propsstate穷劈。props 是在父組件中指定,而且一經(jīng)指定乱陡,在被指定的組件的生命周期中則不再改變。 對于需要改變的數(shù)據(jù),我們需要使用 state沙廉。

state 屬性主要用來存儲組件自身需要的數(shù)據(jù),是組件自己私有的臼节,我們一般通過修改 state 屬性的值來更新數(shù)據(jù)撬陵,React 內(nèi)部會監(jiān)聽 state 的變化珊皿,一旦發(fā)生變化就會主動觸發(fā)組件的 render() 方法來更新 Dom 結(jié)構(gòu)。

state 應(yīng)該是一個 JavaScript 對象巨税。

1.2 state 的使用

一般來說蟋定,你需要在 constructor() 方法中初始化 state(這是ES6的寫法,ES5 中一般在 getInitialState() 方法中來初始化 state)草添,然后在需要修改時調(diào)用 setState() 方法驶兜。

不要使用 this.state 來修改 state 屬性值,應(yīng)該調(diào)用 setState() 方法远寸,this.state 是不可變的抄淑。

2. setState() 方法

setState() 的完整表達式

setState(updater, [callback])

setState() 方法會把對組件 state 的改變加入到隊列中,并且告訴 React 這個組件及其子組件需要重新渲染驰后。

2.1 第一個參數(shù):updater 函數(shù)

setState(updater, callback) 方法的第一個參數(shù)是一個固定格式的 updater 函數(shù):

(prevState, props) => stateChange

prevState 是一個對之前狀態(tài)(previous state)的引用肆资,我們是不能直接修改這個參數(shù)的值,要想修改 state 的值灶芝,我們應(yīng)該根據(jù) prevStateprops 參數(shù)來創(chuàng)建一個新的 JavaScript 對象郑原。
例如:

this.setState((prevState, props) => {
  return {counter: prevState.counter + props.step};
});

你也可以傳一個對象而不是函數(shù),來作為setState(updater, callback) 方法的第一個參數(shù)夜涕,React 會將該參數(shù) merge 到 state 中犯犁。
例如:

this.setState({quantity: 2});

2.2 第二個參數(shù):callback

setState(updater, callback) 方法的第二個參數(shù) callback 是一個可選參數(shù)。

為了更好的性能表現(xiàn)女器,React 并不能保證 setState() 一被調(diào)用 state 就能更新栖秕。所以,如果在調(diào)用 setState() 之后晓避,馬上就讀取 this.state 的值的話簇捍,可能會出現(xiàn)誤差。
因此俏拱,這種情況下暑塑,推薦使用 componentDidUpdate 或者 setState(updater, callback) 方法的 callback 來獲取最新的狀態(tài)。React 官方更推薦使用 componentDidUpdate()锅必,而不是 callback 來監(jiān)聽 update 事件(注: 除非 shouldComponentUpdate() 方法返回 false事格,setState() 將永遠(yuǎn)都會引發(fā)重新渲染)。

3. 正確操作 state

3.1 不要使用 this.state 來直接修改 state

記住搞隐,this.state 是不可變的驹愚。

不要使用 this.state 來修改 state 屬性值:

// Wrong
this.state.comment = 'Hello';

應(yīng)該調(diào)用 setState() 方法:

// Correct
this.setState({comment: 'Hello'});

3.2 狀態(tài)更新可能是異步的

考慮到性能問題,如果在同一個周期內(nèi)劣纲,調(diào)用了多次逢捺,React 可能會將多個 setState() 方法的調(diào)用批量合成一次更新。比如癞季,你在一個周期內(nèi)劫瞳,對一個數(shù)值進行多次累加倘潜,就會出現(xiàn)類似于下面的這種情況:

Object.assign(
  previousState,
  {quantity: state.quantity + 1},
  {quantity: state.quantity + 1},
  ...
)

這也就意味著,后面的調(diào)用會覆蓋掉上一次調(diào)用后的修改的 state 值志于,因此 quantity 只累加了 1 次涮因。

考慮到 this.propsthis.state 可能是異步更新的,所以伺绽,每次調(diào)用 setState() 方法時养泡,最好不要依賴于 this.propsthis.state 來計算最新的 state

總之奈应,如果后面的狀態(tài)依賴于之前的狀態(tài)瓤荔,建議使用 updater 函數(shù):

// Correct
this.setState((prevState, props) => {
  return {quantity: prevState.quantity + 1};
});

上面用的是 箭頭函數(shù) 的形式,其實用普通的函數(shù)也是一樣的效果:

// Correct
this.setState(function(prevState, props) {
  return {
    quantity: prevState.quantity + 1;
  };
});

3.3 狀態(tài)更新是一個合并的過程

當(dāng)你調(diào)用 setState() 方法時钥组,React 會將將你當(dāng)前所提供的對象合并到當(dāng)前的狀態(tài)中输硝。
例如:

constructor(props) {
    super(props);
    this.state = {
      posts: [],
      comments: []
    };
  }

componentDidMount() {

    fetchComments().then(response => {
      this.setState({
        comments: response.comments
      });
    });
  }

在上面??的例子中, state 的更新只是替換了 comments程梦,posts是不會受到任何影響的点把。

4.單向數(shù)據(jù)流

父組件和子組件之間不能通過 state 來交互,父組件只能將自己的 state 值傳給子組件的 props屿附。這種數(shù)據(jù)傳遞的方式通常被稱為 “自頂向下(top-down)”或者“單向(unidirectional)”數(shù)據(jù)流郎逃。

任何 state 都是由一個特定的組件所擁有的,任何由 state 驅(qū)動的數(shù)據(jù)或者 UI 只會影響到該組件的子組件挺份。

如果你將組件樹想象成一個 props 瀑布褒翰,那么每個組件的狀態(tài)就像是那個組件水源上的附屬品,但是也是向下流動的匀泊。

5. 完整示例代碼

'use strict';

import React, { Component, } from 'react';
import {
  AppRegistry,
  StyleSheet,
  View,
  Text,
  TouchableOpacity,
} from 'react-native';


export default class StateDemo extends Component {
  render() {
    return <Container style={styles.container} />;
  }
}


class Container extends Component {
  constructor() {
    super();
    // 設(shè)置初始狀態(tài)
    this.state = {
      showText: true,
    };
  }

  render() {
      // 根據(jù)狀態(tài)決定展示什么文字
      var text = (this.state.showText == true) ? 'Hello' : "";
      var buttonTitle = (this.state.showText == true) ? 'Hide' : "Show";

      return (
        <View style={styles.container}>
          <Text style={styles.text}>{text}</Text>
          <TouchableOpacity
            onPress = {() => {
             // 更新狀態(tài)
              this.setState(
                previousState => {
                  return { showText: !previousState.showText };
                }
              );

            }}>
            <Text style={styles.buttonTitle}>{buttonTitle}</Text>
          </TouchableOpacity>
        </View>
  );
  }
}

 const styles = StyleSheet.create({
   container: {
     flex: 1,
     backgroundColor: 'yellow',
     alignItems: 'center',
   },

   text: {
     marginTop: 200,
     fontSize: 30,
     textAlign: 'center',
   },

   buttonTitle: {
     width: 70,
     marginTop: 10,
     fontSize: 20,
     textAlign: 'center',
     backgroundColor: 'green',
   },

 });

延伸閱讀

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末优训,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子各聘,更是在濱河造成了極大的恐慌揣非,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件躲因,死亡現(xiàn)場離奇詭異早敬,居然都是意外死亡,警方通過查閱死者的電腦和手機大脉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進店門搞监,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人镰矿,你說我怎么就攤上這事琐驴。” “怎么了?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵棍矛,是天一觀的道長。 經(jīng)常有香客問我抛杨,道長够委,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任怖现,我火速辦了婚禮茁帽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘屈嗤。我一直安慰自己潘拨,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布饶号。 她就那樣靜靜地躺著铁追,像睡著了一般。 火紅的嫁衣襯著肌膚如雪茫船。 梳的紋絲不亂的頭發(fā)上琅束,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天,我揣著相機與錄音涩禀,去河邊找鬼。 笑死然眼,一個胖子當(dāng)著我的面吹牛艾船,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播高每,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼屿岂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鲸匿?” 一聲冷哼從身側(cè)響起雁社,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晒骇,沒想到半個月后霉撵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡洪囤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年徒坡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘤缩。...
    茶點故事閱讀 40,926評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡喇完,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出剥啤,到底是詐尸還是另有隱情锦溪,我是刑警寧澤不脯,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站刻诊,受9級特大地震影響防楷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜则涯,卻給世界環(huán)境...
    茶點故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一复局、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧粟判,春花似錦亿昏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至呻澜,卻和暖如春彤断,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背易迹。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工宰衙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人睹欲。 一個月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓供炼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親窘疮。 傳聞我的和親對象是個殘疾皇子袋哼,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,930評論 2 361

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