[React Native] React 中的状态(State)

目录

  • 1.state 属性
    • 1.1 state属性的介绍
    • 1.2 state 的使用
  • 2.setState() 方法
    • 2.1 第一个参数:updater 函数
    • 2.2 第二个参数:callback
  • 3.正确操作 state
    • 3.1 不要使用 this.state 来直接修改 state
    • 3.2 状态更新可能是异步的
    • 3.3 状态更新是一个合并的过程
  • 4.单向数据流
  • 5.完整示例代码

state 属性是 React 组件用来更新数据的核心特性,也是我们平时见得最多的属性之一,那么你对 state 又了解多少呢?

1. state 属性

1.1 state属性的介绍

我们使用两种数据来控制一个组件:propsstateprops 是在父组件中指定,而且一经指定,在被指定的组件的生命周期中则不再改变。 对于需要改变的数据,我们需要使用 state

state 属性主要用来存储组件自身需要的数据,是组件自己私有的,我们一般通过修改 state 属性的值来更新数据,React 内部会监听 state 的变化,一旦发生变化就会主动触发组件的 render() 方法来更新 Dom 结构。

state 应该是一个 JavaScript 对象。

1.2 state 的使用

一般来说,你需要在 constructor() 方法中初始化 state(这是ES6的写法,ES5 中一般在 getInitialState() 方法中来初始化 state),然后在需要修改时调用 setState() 方法。

不要使用 this.state 来修改 state 属性值,应该调用 setState() 方法,this.state 是不可变的。

2. setState() 方法

setState() 的完整表达式

setState(updater, [callback])

setState() 方法会把对组件 state 的改变加入到队列中,并且告诉 React 这个组件及其子组件需要重新渲染。

2.1 第一个参数:updater 函数

setState(updater, callback) 方法的第一个参数是一个固定格式的 updater 函数:

(prevState, props) => stateChange

prevState 是一个对之前状态(previous state)的引用,我们是不能直接修改这个参数的值,要想修改 state 的值,我们应该根据 prevStateprops 参数来创建一个新的 JavaScript 对象。
例如:

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

你也可以传一个对象而不是函数,来作为setState(updater, callback) 方法的第一个参数,React 会将该参数 merge 到 state 中。
例如:

this.setState({quantity: 2});

2.2 第二个参数:callback

setState(updater, callback) 方法的第二个参数 callback 是一个可选参数。

为了更好的性能表现,React 并不能保证 setState() 一被调用 state 就能更新。所以,如果在调用 setState() 之后,马上就读取 this.state 的值的话,可能会出现误差。
因此,这种情况下,推荐使用 componentDidUpdate 或者 setState(updater, callback) 方法的 callback 来获取最新的状态。React 官方更推荐使用 componentDidUpdate(),而不是 callback 来监听 update 事件(注: 除非 shouldComponentUpdate() 方法返回 falsesetState() 将永远都会引发重新渲染)。

3. 正确操作 state

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

记住,this.state 是不可变的。

不要使用 this.state 来修改 state 属性值:

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

应该调用 setState() 方法:

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

3.2 状态更新可能是异步的

考虑到性能问题,如果在同一个周期内,调用了多次,React 可能会将多个 setState() 方法的调用批量合成一次更新。比如,你在一个周期内,对一个数值进行多次累加,就会出现类似于下面的这种情况:

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

这也就意味着,后面的调用会覆盖掉上一次调用后的修改的 state 值,因此 quantity 只累加了 1 次。

考虑到 this.propsthis.state 可能是异步更新的,所以,每次调用 setState() 方法时,最好不要依赖于 this.propsthis.state 来计算最新的 state

总之,如果后面的状态依赖于之前的状态,建议使用 updater 函数:

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

上面用的是 箭头函数 的形式,其实用普通的函数也是一样的效果:

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

3.3 状态更新是一个合并的过程

当你调用 setState() 方法时,React 会将将你当前所提供的对象合并到当前的状态中。
例如:

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

componentDidMount() {

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

在上面👆的例子中, state 的更新只是替换了 commentsposts是不会受到任何影响的。

4.单向数据流

父组件和子组件之间不能通过 state 来交互,父组件只能将自己的 state 值传给子组件的 props。这种数据传递的方式通常被称为 “自顶向下(top-down)”或者“单向(unidirectional)”数据流。

任何 state 都是由一个特定的组件所拥有的,任何由 state 驱动的数据或者 UI 只会影响到该组件的子组件。

如果你将组件树想象成一个 props 瀑布,那么每个组件的状态就像是那个组件水源上的附属品,但是也是向下流动的。

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();
    // 设置初始状态
    this.state = {
      showText: true,
    };
  }

  render() {
      // 根据状态决定展示什么文字
      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 = {() => {
             // 更新状态
              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',
   },

 });

延伸阅读

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容