React状态
React的状态一般要先在构造函数中进行初始化声明。
constructor(props) {
super(props);
//初始化状态,将所有的状态都放到下面的state对象里面
this.state = {
date: new Date()
....
};
}
React的状态的修改一定要使用setState,如下:
constructor(props) {
super(props);
//初始化状态,将所有的状态都放到下面的state对象里面
this.state = {
date: new Date(),
num:0,
....
};
}
componentDidMount(){
// 修改状态中的num的值
this.setState({
num:20
})
}
案例,下面是一个显示当前时间的组件,时间使用props传递的(可以看组件传值讲解),页面显示的是固定的值不能实时变化,
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2> // It is 下午2:08:20.
</div>
);
}
}
ReactDOM.render(
<Clock date={new Date()}/>,
document.getElementById("app")
)
现在我们要实现时间实时变化更新的功能 :
将本地状态添加到类中,我们将date参数分三步从props转移到state
1.更换this.props.date用this.state.date的render()方法:
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
---------------------------------------------------------------------------
2.添加一个分配初始化的类构造函数创建本地状态this.state,
class Clock extends React.Component {
constructor(props) {
super(props);
//初始化状态
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
---------------------------------------------------------------------------
3.date从<Clock />元素中删除prop :
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
将生命周期方法添加到类中:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() { // 组件装载完成,更新数据
this.timerID = setInterval( // 每隔1秒,调用this._tick(),更新状态
() => this._tick(),
1000
);
}
componentWillUnmount() { // 组件销毁时,删除定时器
clearInterval(this.timerID);
}
render() { // 渲染视图组件
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
_tick() { // 自定义方法,更新状态的值
this.setState({
date: new Date()
});
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
让我们快速回顾一下上面的组件执行过程,发生了什么以及调用这些方法的顺序:
1.当<Clock />被传递到ReactDOM.render(),Clock组件构造函数constructor被执行。初始化本地状态this.state
2.然后React调用Clock组件的render()方法。更新DOM以匹配Clock渲染输出。
3.当Clock输出插入DOM时,React会调用componentDidMount()生命周期方法。在其中设置了一个计时器,每秒调用一次组件的方法tick()。
4.浏览器每次调用该tick()方法。Clock组件通过setState()方法更新state。由于setState()调用,React知道状态已经改变,会再次调用render()重新渲染。此时,this.state.date在render()方法中是改变后的值。
5.如果Clock组件从DOM中删除,React会调用componentWillUnmount()生命周期方法,来停止计时器。
state的正确使用:
//不要直接修改状态:
this.state.comment = 'Hello'; // 错误
//使用setState():
this.setState({comment: 'Hello'}); // 正确
状态更新可能是异步的:
this.setState({
counter: this.state.counter + this.props.increment,
});
上例中,this.props和this.state可以异步的,所以不应该依赖它们的值来计算下一个状态。上面的代码可能无法更新计数器,此时要使用第二种形式setState()接受函数而不是对象,如下:
this.setState(function(state, props) {
return {
counter: state.counter + props.increment
};
});
箭头函数:
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
单组件中props和state区别
1.固定不变的数据放在props,变化的数据放在state中。props主要用途用于复合组件中父子组件之间的传值
2.props里面的数据是只读的,只能读取,不能更改设置。state里面的数据既可以读取也可以更改
class Dog extends React.Component{
constructor(props){
super(props)
//初始化状态
// 姓名,性别,年龄,朋友
this.state = {
age : 1,
friends:["花花","小红"]
}
}
//设置props属性的默认值
static defaultProps = {
name:"旺财",
gender:"公"
}
//设置props属性的类型(需要外部引入prop-types.js)
static propTypes = {
name:PropTypes.string.isRequired, // 必传项
gender:PropTypes.string,
}
changeAge(){
this.setState({
age:this.state.age+1
})
}
render(){
const {name,gender} = this.props
const {age,friends} = this.state
return (
<div>
<p>狗名:{name},性别:{gender}</p>
<p>年龄:{age}</p>
<p>朋友</p>
<ul>
{
friends.map((friend,index)=>(
<li key={index}>{friend}</li>
))
}
</ul>
<button onClick={()=>this.changeAge()}>点击增长年龄</button>
</div>
)
}
}
ReactDOM.render(<Dog name="" gender="母" />,document.getElementById('app'))