Skip to content

Commit d04fd3d

Browse files
committed
feat[ptr]: 如果setState改变状态的代码处于某个HTML元素的事件中,则其是异步的,否则是同步
如果要使用改变之后的状态,需要使用回调函数 如果新的状态要根据之前的状态链式作用,需要使用函数的方式改变状态 同时React会对异步的setState进行优化,将多次setState进行合并
1 parent 9a14c44 commit d04fd3d

5 files changed

Lines changed: 240 additions & 7 deletions

File tree

React/sandboxs/src/index.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,32 @@ import ReactDOM from 'react-dom';
2323
// </>
2424
// )
2525

26-
// import NumState from './test/NumState';
26+
import StateInEvent from './test/StateInEvent';
2727

28-
import { Btn, MyBtn } from './test/Event';
28+
// import { Btn, MyBtn } from './test/Event';
2929

30-
const callback = () => console.log("我被电击了")
30+
// const callback = () => console.log("我被电击了")
31+
// const el = (
32+
// <div>
33+
// {Btn()}
34+
// <MyBtn callback={callback} onClick={() => console.log("自定义组件的onClick")} />
35+
// </div>
36+
// )
37+
38+
import StateNotInEvent from './test/StateNotInEvent'
39+
import StateMulCallBack from './test/StateMulCallBack'
40+
import StateMulNotSync from './test/StateMulNotSync'
3141
const el = (
32-
<div>
33-
{Btn()}
34-
<MyBtn callback={callback} onClick={() => console.log("自定义组件的onClick")} />
35-
</div>
42+
<>
43+
<h1>StateInEvent</h1>
44+
<StateInEvent number={5} />
45+
<h1>StateNotInEvent</h1>
46+
<StateNotInEvent number={5} />
47+
<h1>StateMulCallBack</h1>
48+
<StateMulCallBack number={5} />
49+
<h1>StateMulNotSync</h1>
50+
<StateMulNotSync number={5} />
51+
</>
3652
)
53+
3754
ReactDOM.render(el, document.getElementById('root'))
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React from 'react'
2+
// import { h1 } from 'framer-motion/client'
3+
// 注意 tab 后可能会自动导入无关数据
4+
5+
export default class NumState extends React.Component {
6+
state = {
7+
num: this.props.number
8+
}
9+
handleClick = () => {
10+
console.log(" ")
11+
console.log("=== StateInEvent start")
12+
this.setState(
13+
{
14+
num: this.state.num - 1
15+
}
16+
)
17+
console.log("=== num", this.state.num)
18+
}
19+
render() {
20+
console.log("=== render")
21+
console.log("=== num", this.state.num)
22+
return (
23+
<>
24+
<h1>{this.state.num}</h1>
25+
<button onClick={this.handleClick}>-</button>
26+
</>
27+
)
28+
}
29+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import React from 'react'
2+
// import { h1 } from 'framer-motion/client'
3+
// 注意 tab 后可能会自动导入无关数据
4+
5+
export default class NumState extends React.Component {
6+
state = {
7+
num: this.props.number
8+
}
9+
handleClick = () => {
10+
console.log(" ")
11+
console.log("=== StateMulCallBack start")
12+
this.setState(prev => {
13+
// setState 第一个参数也可以是一个函数
14+
// 参数prev表示当前的状态
15+
// 该函数的返回结果,会混合(覆盖)掉之前的状态
16+
// 该函数是异步执行
17+
return {
18+
num: prev.num - 1
19+
}
20+
})
21+
this.setState(prev => {
22+
return {
23+
num: prev.num - 1
24+
}
25+
})
26+
this.setState(prev => {
27+
return {
28+
num: prev.num - 1
29+
}
30+
})
31+
// , // setState的第二个参数:状态完成之后的回调函数
32+
// () => {
33+
// this.setState(
34+
// {
35+
// num: this.state.num - 1
36+
// }, this.setState(
37+
// {
38+
// num: this.state.num - 1
39+
// }))
40+
// })
41+
42+
// 多个并行的 setState 都是在 同一个之前状态 基础进行的操作,所以会被覆盖,
43+
// 正确应该是像上面一样在状态完成之后再进行操作
44+
// this.setState(
45+
// {
46+
// num: this.state.num - 1
47+
// })
48+
49+
// this.setState(
50+
// {
51+
// num: this.state.num - 1
52+
// })
53+
}
54+
render() {
55+
// 并且 React会对异步的setState进行优化,将多次setState进行合并
56+
// 所以一次点击虽然事件中有三次 setState ,但是只会有一次 render
57+
console.log("=== StateMulNotSync render")
58+
console.log("=== num", this.state.num)
59+
return (
60+
<>
61+
<h1>{this.state.num}</h1>
62+
<button onClick={this.handleClick}>-</button>
63+
</>
64+
)
65+
}
66+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import React from 'react'
2+
// import { h1 } from 'framer-motion/client'
3+
// 注意 tab 后可能会自动导入无关数据
4+
5+
export default class NumState extends React.Component {
6+
state = {
7+
num: this.props.number
8+
}
9+
constructor(props) {
10+
super(props)
11+
setInterval(() => {
12+
this.setState(prev => {
13+
// setState 第一个参数也可以是一个函数
14+
// 参数prev表示当前的状态
15+
// 该函数的返回结果,会混合(覆盖)掉之前的状态
16+
// 该函数是异步执行
17+
return {
18+
num: prev.num - 1
19+
}
20+
})
21+
this.setState(prev => {
22+
return {
23+
num: prev.num - 1
24+
}
25+
})
26+
this.setState(prev => {
27+
return {
28+
num: prev.num - 1
29+
}
30+
})
31+
}, 2000);
32+
}
33+
handleClick = () => {
34+
console.log(" ")
35+
console.log("=== StateMulCallBack start")
36+
this.setState(prev => {
37+
// setState 第一个参数也可以是一个函数
38+
// 参数prev表示当前的状态
39+
// 该函数的返回结果,会混合(覆盖)掉之前的状态
40+
// 该函数是异步执行
41+
return {
42+
num: prev.num - 1
43+
}
44+
})
45+
this.setState(prev => {
46+
return {
47+
num: prev.num - 1
48+
}
49+
})
50+
this.setState(prev => {
51+
return {
52+
num: prev.num - 1
53+
}
54+
})
55+
// , // setState的第二个参数:状态完成之后的回调函数
56+
// () => {
57+
// this.setState(
58+
// {
59+
// num: this.state.num - 1
60+
// }, this.setState(
61+
// {
62+
// num: this.state.num - 1
63+
// }))
64+
// })
65+
66+
// 多个并行的 setState 都是在 同一个之前状态 基础进行的操作,所以会被覆盖,
67+
// 正确应该是像上面一样在状态完成之后再进行操作
68+
// this.setState(
69+
// {
70+
// num: this.state.num - 1
71+
// })
72+
73+
// this.setState(
74+
// {
75+
// num: this.state.num - 1
76+
// })
77+
}
78+
render() {
79+
// 并且 React会对异步的setState进行优化,将多次setState进行合并
80+
// 所以一次点击虽然事件中有三次 setState ,但是只会有一次 render
81+
console.log("=== render")
82+
console.log("=== num", this.state.num)
83+
return (
84+
<>
85+
<h1>{this.state.num}</h1>
86+
<button onClick={this.handleClick}>-</button>
87+
</>
88+
)
89+
}
90+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React from 'react'
2+
// import { h1 } from 'framer-motion/client'
3+
// 注意 tab 后可能会自动导入无关数据
4+
5+
export default class NumState extends React.Component {
6+
state = {
7+
num: this.props.number
8+
}
9+
handleClick = () => {
10+
console.log(" ")
11+
console.log("=== StateNotInEvent start")
12+
this.setState(
13+
{
14+
num: this.state.num - 1
15+
}
16+
, // setState的第二个参数:状态完成之后的回调函数
17+
() => {
18+
console.log("=== num 状态完成之后的回调函数", this.state.num)
19+
})
20+
}
21+
render() {
22+
console.log("=== render")
23+
console.log("=== num", this.state.num)
24+
return (
25+
<>
26+
<h1>{this.state.num}</h1>
27+
<button onClick={this.handleClick}>-</button>
28+
</>
29+
)
30+
}
31+
}

0 commit comments

Comments
 (0)