1.setState会将多个setState合并成一个,以最后一个优先;
React 采用批量更新机制,setState 并不会立刻修改 state,而是等待下一次渲染时更新
当调用 setState 在当前执行上下文中是获取不到最新的 state, 只有在下一次组件 rerender 中才能获取到
setState 除了能传递一个值外,还可以传入回调函数,回调函数的参数就是最新的 state 的值
更新状态会触发组件重新渲染
function App() {
const [count1, setCount1] = React.useState(0)
const handleClick1 = () => {
setCount1(count1 + 1)
setCount1(count1 + 1)
console.log(count1)
}
const [count2, setCount2] = React.useState(0)
const handleClick2 = () => {
setCount2((count2) => {
return count2 + 1
})
setCount2((count2) => {
return count2 + 1
})
}
console.log('我是render')
return (
<div>
<p>You clicked {count1} times</p>
<button onClick={handleClick1}>Click me</button>
<p>You clicked {count2} times</p>
<button onClick={handleClick2}>Click me</button>
</div>
)
}
初始化的时候:我是render
每次点击handleClick1都只会count1+1
每次点击handleClick2都会count2+2
2.useState 的初始值有两种情况:第一种情况是非函数,将作为 state 初始化的值;
第二种情况是函数,函数的返回值作为 useState初始化的值,只在组件首次渲染时生效,为同步代码。
function App() {
const handleClick = () => {
setName(6666)
}
const [name, setName] = React.useState(() => {
console.log('init name state')
return 'LinDaiDai'
})
console.log('我是render')
const [name2, setName2] = React.useState(() => {
console.log('init name2 state')
return 'LinDaiDai2'
})
return (
<div>
<p>{name}</p>
<button onClick={handleClick}>Click me</button>
</div>
)
}
初始化:
init name state
我是render
init name2 state
点击handleClick:
我是render
3.useState 的初始值传递的如果是函数中的计算内容,那么这个计算会在每次渲染的时候都执行,但不会重新赋值
let nums = 0
function App() {
const [count, setCount] = React.useState(0)
function getNum() {
nums = nums + 1
console.log('getNum', nums)
return nums
}
const [count2, setCount2] = React.useState(getNum() * 10)
const handleClick1 = () => {
setCount(count + 1)
}
const handleClick2 = () => {
setCount2(count2 + 1)
}
console.log('我是render')
return (
<div>
<p>{count}</p>
<button onClick={handleClick1}>Click me</button>
<p>{count2}</p>
<button onClick={handleClick2}>Click me</button>
</div>
)
}
初始化:
getNum 1
我是render
点击handleClick1:
getNum 2(但是不影响count2值)
我是render
点击handleClick2:
getNum 3(但是不影响count2值)
我是render
4.在调用 setState 去更新状态的时候,React 内部会进行类似 Object.is() 这样的浅比较,如果值相等则不会重新渲染
const [count3, setCount3] = React.useState(0)
const [person, setPerson] = React.useState({ name: 'LinDaiDai' })
<button
onClick={() => {
setCount3(0)
}}
>
Click me
</button>
<br />
<button
onClick={() => {
setPerson({ name: 'LinDaiDai22' })
// person.name = 'Gisika';
// setPerson(person);
// setPerson({ name: 'LinDaiDai1' })
}}
>
Modify name
</button>
5.简单实现useStatus的demo
// 1. 初始定义数组和下标
let _state = []
let index = 0
function useMyState(initialState) {
// 2. 在每次调用 useMyState 的时候,把当前这个 state 的下标缓存起来
let currentIndex = index
// 3. 赋值
_state[currentIndex] =
_state[currentIndex] === undefined
? initialState
: _state[currentIndex]
function setState(newState) {
// 5. 外界更新的时候,由于 setState 和 useMyState 形成了闭包,这里能获取到 currentInex,并成功更新数组中对应下标的值
_state[currentIndex] = newState
index = 0
render()
}
// 4. 在调用完一次 useMyState 之后,就要把 index 累加了,方便下一个 state 调用的时候知道自己应该排在哪
index += 1
return [_state[currentIndex], setState]
}
const [count, setCount] = useMyState(0)