setState原理揭秘
2022年10月1日更新数据
- setState()是异步更细数据的
- 注意:使用该语法时,后面的setState()不要依赖于前面的setState()
- 当你调用setState()的时候React不会马上修改state而是把这个对象放到一个更新队列里面,稍后才会从队列当中把新的状态提取出来合并到state当中,然后更新出发组件更新
- 可以调用多次setState,只会触发一次重新渲染
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 |
import React, {Component} from 'react'; import ReactDOM from "react-dom"; class Index extends Component { state = { count: 0 } render() { return ( <div> {this.state.count} <button onClick={this.addCount}>数量+1</button> </div> ); } addCount = () => { this.setState({ count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 }) console.log(this.state.count) //这里console.log()结果是 0因为是异步的, 页面结果是1多条setState合并了 } } ReactDOM.render(<Index></Index>, document.getElementById('root')) |
- 解决多条setState 造成的数据不能连贯问题
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 |
import React, {Component} from 'react'; import ReactDOM from "react-dom"; class Index extends Component { state = { count: 0 } render() { return ( <div> {this.state.count} <button onClick={this.addCount}>数量+1</button> </div> ); } addCount = () => { this.setState((preState) => { return { count: preState.count + 1 } }) this.setState((preState) => { return { count: preState.count + 1 } }) this.setState((preState) => { return { count: preState.count + 1 } }) console.log(this.state.count) //这里console.log()结果是 0因为是异步的, 页面结果是3 ,参数preState: React.js 会把上一个 `setState` 的结果传入这个函数 } } ReactDOM.render(<Index></Index>, document.getElementById('root')) |
在状态更新后立即执行某个操作,使用了setState第二个参数
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 |
import React, {Component} from 'react'; import ReactDOM from "react-dom"; class Index extends Component { state = { count: 0 } render() { return ( <div> {this.state.count} <button onClick={this.addCount}>数量+1</button> </div> ); } addCount = () => { this.setState((preState) => { return { count: preState.count + 1 } }) this.setState((preState) => { return { count: preState.count + 1 } }) this.setState((preState) => { return { count: preState.count + 1 } },()=>{ console.log(this.state.count) //这里console.log()结果是 3, 页面结果是3 }) } } ReactDOM.render(<Index></Index>, document.getElementById('root')) |
组件更新
1.功能第一
2.性能第二
- 减轻state:只存跟组件渲染相关的数据 比如列表数据/loading等
- 不做渲染的数据不要放在state中,比入定时器ID等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Hello extends Component { componentDidMount() { // timerId存储到this中,而不是state中 this.timerId = setInterval(() => { }, 2000) } componentWillUnmount() { clearInterval(this.timerId) } render() { … } } |
- 对于这种需要在多个方法中用到的数据,应该直接放在this中
避免不必要的重新渲染
- 组件更新机制:父组件更新会引起子组件也被更新
- 子组件没有任何变化时也会重新渲染 (接收到的props没有发生任何的改变)
- + 解决方式:使用钩子函数
shouldComponentUpdate(nextProps, nextState)
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 |
import React, {Component} from 'react'; import ReactDOM from "react-dom"; class Son extends Component { render() { return (<div>你好世界{this.props.sonCount}</div>) } /** * 如果父组件更新了,判断传入的参数和当前参数有没有变化, * 如果有变化更新组件,没有不更新 */ shouldComponentUpdate(nextProps, nextState, nextContext) { if (JSON.stringify(nextProps) === JSON.stringify(this.props)) { console.log('没有更新') return false } else { console.log('更新了') return true } } } class Index extends Component { state = { count: 0, sonCount: 0 } render() { return ( <div> {this.state.count} <button onClick={this.addCount}>数量+1</button> <button onClick={() => { this.setState({sonCount: this.state.sonCount + 1}) }}>子+1 </button> <hr/> <Son sonCount={this.state.sonCount}></Son> </div> ); } addCount = () => { this.setState({ count: this.state.count + 1 }) } } ReactDOM.render(<Index></Index>, document.getElementById('root')) |
使用纯组件
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 |
import React, {Component, PureComponent} from 'react'; import ReactDOM from "react-dom"; class Son extends PureComponent { render() { return (<div>你好世界{this.props.sonCount}</div>) } /** * 如果继承 Component 父组件更新的时后子组件也会更新会打印 1 * 如果继承 PureComponent 父组件更新的时候 会判断有没有更新子组件数据 * 如果没有不会打印 */ componentDidUpdate(prevProps, prevState, snapshot) { console.log(1) } } class Index extends Component { state = { count: 0, sonCount: 0 } render() { return ( <div> {this.state.count} <button onClick={this.addCount}>数量+1</button> <button onClick={() => { this.setState({sonCount: this.state.sonCount + 1}) }}>子+1 </button> <hr/> <Son sonCount={this.state.sonCount}></Son> </div> ); } addCount = () => { this.setState({ count: this.state.count + 1 }) } } ReactDOM.render(<Index></Index>, document.getElementById('root')) |