State
如何组织数据是程序的最重要问题。Raect组件的数据分为两种:prop和state。无论prop还是state的改变,都可能引发组件的重新渲染。
状态state和属性props十分相似,但是状态是私有的,完全受控于当前组件。prop是组件的对外接口,state是组件的内部状态。由于React不能直接修改传入的prop,所以需要记录自身数据变化,就要使用state。
state和prop的区别
- prop用于定义外部接口,state用于记录内部状态
- prop的赋值在父组件使用该组件时,state的赋值在该组件内部
- 组件不可修改prop的值,而state存在的目的就是让组件来改变
组件的state,相当于组件的记忆,其存在意义就是被改变,每一次通过this.setState 函数修改state就改变了组件的状态,然后通过渲染过程把这种变化体现出来。
正确使用state
- 不要直接更新装状态,构造函数是唯一能够初始化this.state 的地方。如果直接修改组件的内部状态,虽然事实上改变了组件的内部状态,但只是野蛮的修改了state,但没有驱动组件进行重新渲染。而this.setState() 函数所做的事情,就是先改变this.state的值,然后驱动组件重新渲染
this.state.comment = "hello"; // wrong
this.setState({comment: "hello"});
- 状态更新可能是异步的,setState 是异步更新的,而不是同步更新。例子:
setYear() {
let {year} = this.state
this.setState({
year: year + 10 // 新值
})
console.log(this.state.year) // 旧值
}
setYear() {
setTimeout(() => {
this.setState({
year: year + 10 // 新值
})
console.log(this.state.year) // 新值
})
}
因为 this.prop 和 this.state 可能是异步更新的,不应该依靠它们的来计算下一个状态。
// wrong
this.setState({
counter: this.state.counter + this.props.increment,
})
要修复它,要使用第二种形式的 setState() 来接受一个函数而不是一个对象。该函数将接收先前的状态作为第一个参数,将此次更新被应用时的 props 做为第二个参数:
// correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment,
}))
- 状态更新合并,可以调用 setState() 独立更新它们,但React将多个 setState() 调用合并成一个调用来提高性能。
componentDidMount() {
fetchPosts().then(response => {
this.setState({
posts: response.posts
});
});
fetchComments().then(response => {
this.setState({
comments: response.comments
});
});
}
这里的合并是浅合并,也就是说 this.setState({comments}) 完整保留了 this.state.posts,但完全替换了this.state.comments。
- 回调函数,由于setState 是异步更新,如果需要确定setState 更新后,再进行某些操作,可以使用setState 的回调函数。
this.setState({
val: value
}, () => {
this.ref.editInput.focus()
})
网友评论