[TOC]

概述

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

一般来说,你需要在 constructor 中初始化state(译注:这是 ES6 的写法,早期的很多 ES5 的例子使用的是 getInitialState 方法来初始化 state,这一做法会逐渐被淘汰),然后在需要修改时调用setState方法。

假如我们需要制作一段不停闪烁的文字。文字内容本身在组件创建时就已经指定好了,所以文字内容应该是一个prop。而文字的显示或隐藏的状态(快速的显隐切换就产生了闪烁的效果)则是随着时间变化的,因此这一状态应该写到state中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

import React, { Component } from 'react';
// 从“react-native” 导入以下这些控件
import { Platform, StyleSheet, Text, View, Image } from 'react-native';

const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});

type Props = {};
export default class App extends Component<Props> {
render() {
// 声明图片
let pic = {
uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg'
};

return (
// 给整体的VIew设置相同的属性。属性字段为styles.container
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>To get started, edit App.js</Text>
<Text style={styles.instructions}>{instructions}</Text>
{/* 添加自定义闪烁组件 */}
<CustomStateComponent name="State 欢迎学习RN" />
{/* 通过source 和style这两个属性来给图片设置样式 */}
<Image source={pic} style={{ width: 193, height: 110 }} />
</View>
);
}
}

// 通过StyleSheet的来创建样式。通过创建
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#C5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
color: '#FE3333',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});


// 我们可以通过继承自Components来创建自定义组件
/**
* 创建一个自定义View的组件
*
* 制作一段不停闪烁的文字。文字内容本身在组件创建时就已经指定好了,所以文字内容应该是一个prop。
* 而文字的显示或隐藏的状态(快速的显隐切换就产生了闪烁的效果)则是随着时间变化的,因此这一状态应该写到state中。
*/
class CustomStateComponent extends Component {
// 一般来说,我们需要在构造函数中来进行初始化State
constructor(props) {
super(props);
// 构造函数初始状态设置显示与否的逻辑.首先设置显示文字
this.state = { isShowingText: true };

// 每1000毫秒对showText状态做一次取反操作
setInterval(() => {
// 入参是之前的状态
this.setState(previousState => {
return { isShowingText: !previousState.isShowingText };
});
}, 1000);
}

render() {

// {/* 根据当前isShowingText的值决定是否显示text内容 */}
if (!this.state.isShowingText) {
return null;
}
return (
<View style={{ alignItems: 'center', marginTop: 50 }}>
{/* 自定义组件里面比较简单,其实就是一个自定义的Text的View */}
{/* 我们可以通过传入自定义组件的属性字段,来设置名字 */}
<Text>你好 {this.props.name}!</Text>
</View>
);
}
}

实际开发中,我们一般不会在定时器函数(setInterval、setTimeout 等)中来操作 state。典型的场景是在接收到服务器返回的新数据,或者在用户输入数据之后。你也可以使用一些“状态容器”比如Redux来统一管理数据流。

每次调用setState时,BlinkApp 都会重新执行 render 方法重新渲染。这里我们使用定时器来不停调用setState,于是组件就会随着时间变化不停地重新渲染。

State 的工作原理和 React.js 完全一致,所以对于处理 state 的一些更深入的细节,你可以参阅React.Component API

1、一切界面变化都是状态state变化
2、state的修改必须通过setState()方法

  • this.state.likes = 100; // 这样的直接赋值修改无效!
  • setState 是一个 merge 合并操作,只修改指定属性,不影响其他属性
  • setState 是异步操作,修改不会马上生效

看到这里,你可能觉得我们的例子总是千篇一律的黑色文本,太特么无聊了。那么我们一起来学习一下样式吧。