React——关于setState
一.为什么使用setState?
1)作用
为了管理和维护React中的状态,除了Redux转态管理器,React内部提供了setState来进行组件内的状态管理。
2)基本使用
a.向setState中传入一个对象对已有的state进行更改
b.setState可以接受一个函数作为参数,这个函数返回也是一个对象,同上,但是该函数参数为state的前一个状态以及props
c.setState可以接受两个参数,第一个可以是a,b两种情况。第二个参数是回调函数,始终是执行完setState后再执行回调函数。
/*
void setState (
function|object nextState,
[function callback]
)
*/
class Home extend React.component{ constructor(props){ super(props); this.state{ number:1, } }
//a changeA=()=>{ this.setState({ number:2, }) } //b changeB=()=>{ this.setState((preState,props)=>{ return ({ number:preState.number+1, }) }) } //c changeC=()=>{ this.setState({ number:3, },callback=>{ console.log('执行完setState后,再执行这个回调函数') }) } }
二.setState到底干了什么?
1)执行setState()后做了什么?
setState通过一个队列机制实现state的更新,当执行setState()的时候,会将需要更新的state合并之后放入状态队列,而不会立即更新this.state(可以和浏览器的事件队列类比)。如果我们不使用setState而是使用this.state.key来修改,会修改但是将不会触发组件的re-render(不渲染)。
2)注意:
a.不要使用this.state直接修改state,(因为修改后不render,导致显示的内容和实际存在的state不一致),用setState代替;
b.state更新可能是异步的。不要用this.setState({this.state.number+this.props.xxx}),由于异步可能获取不到你想要的内容。此时需要使用上面所说第一个问题基本使用的b方法。
c.state更新会被合并。当你调用 setState(), React 将合并你提供的对象到当前的状态中。所以当State是一个多键值的结构时,可以单独更新其中的一个,此时会进行“差分”更新,不会影响其他的属性值。
三.setState是同步的还是异步的?
由 React 控制的事件处理过程 setState 不会同步更新 this.state!
也就是说,在 React 控制之外的情况, setState 会同步更新 this.state!(如下边例子setTimeOut()函数内)
class page extends Component { state = { name: 'xxx', age: 20, } onClickDiv = () => { this.setState((prevState, props) => { console.log('11-------', prevState); return ({ name: 'xxx11', }) }) this.setState((prevState, props) => { console.log('22-------', prevState); return ({ name: 'xxx22', age: 30, }) }) console.log('异步还是同步1111????'); setTimeout(() => { this.setState({ name: 'xxx33' }) console.log('异步还是同步2222????'); this.setState((prevState, props) => { console.log('33-------', prevState); return ({ name: 'xxx44', }) }) console.log('异步还是同步3333????', this.state.name); this.setState((prevState, props) => { console.log('44-------', prevState); return ({ name: 'xxxx55', }) }) console.log('异步还是同步4444????', this.state.name); this.setState({ name: 'xxxx66' }, () => { console.log('完成'); }) console.log('异步还是同步5555????', this.state.name); this.state.name = 'xxxx77' }, 2000); } render() { const { name, age } = this.state console.log(name, age); return ( <div onClick={() => this.onClickDiv()}> {name}nihao{age} <div className={styles.contentMap}> <div id="map" className={styles.map}></div> </div> </div> ) } } /* ====================点击第1次-----setTimeOut外表现异步,内表现同步============= 异步还是同步1111???? 11------- {name: "999888", age: 20} 22------- {name: "xxx11", age: 20} xxx22 30 xxx33 30 异步还是同步2222???? 33------- {name: "xxx33", age: 30} xxx44 30 异步还是同步3333???? xxx44 44------- {name: "xxx44", age: 30} xxxx55 30 异步还是同步4444???? xxxx55 xxxx66 30 完成 异步还是同步5555???? xxxx66 ====================点击第2次--this.state能修改但未render============= 异步还是同步1111???? 11------- {name: "xxxx77", age: 30} ... */
参考:https://www.jianshu.com/p/a883552c67de
浙公网安备 33010602011771号