useState
在 React 16.8 版本之前,函数组件被用于编写 简单的 UI 组件和无状态组件。如果需要在函数组件中使用状态,就需要将其转换为类组件,这增加了代码复杂度,同时也不便于代码的维护。因此,React 团队引入了 Hook 机制,使得函数组件也可以方便地使用状态、生命周期等特性。
- 函数组件也是一个
普通函数,函数执行完就会被销毁了,那么自然它的状态也就没法保存只有返回值。为了让函数组件有自己的状态(指的时你声明的响应式变量)React 引入了 Hook 使得你的状态可以存留在函数里。当函数里面的值被引用时那么它就会形成一个闭包。所以说函数组件就是一个闭包。
useState 的使用
调用 useState 方法,传入一个初始值, 返回的一个数组。
语法:
const [state, setState] = useState(initialState);
initialState:状态的初始值(也可以是一个函数下面演示)。state:初始值响应式状态。setState:用于更新状态的函数,每次调用它都会重新渲染组件。
在函数组件中改变状态时使用 set(setState)方法有两种形式 直接更新 和 函数式更新
直接更新 和 函数式更新
import React, { useState } from "react";
const [state, setState] = useState(0);
export default const App = ()=>{
// 直接更新
function handleClick() {
/**
* state = 5
* 直接赋值 并不会更新
* */
setState(count + 1);
}
// 函数式更新 set 方法接收一个函数
function handleClickFn() {
setState((prevState) => {
// prevCount上一次 state 最新的值
return prevState + 1;
});
}
return (
<div>
State: {State}
<button onClick={handleClick}>直接更新</button>
<button onClick={handleClickFn}>函数式更新</button>
</div>
);
}
直接更新set 方法直接传入需要更新的值就行函数式更新set 方法接受一个函数,这个函数的返回值就是需要更新的值
划重点:
函数组件中 你直接修改 响应式状态的值(state)并不会更新,必须调用它对应的
set 方法才可以刷新视图
直接更新 与 函数式更新 的使用场景
- 当我们加一个定时器就能看出他们两的不同了
import React, { useState } from "react";
export default const App = ()=>{
// useStaet 初始值接受一个参数
function getState() {
let a = 1
let b = 1
return a + b;
}
const [state, setState] = useState(getState);
// 直接更新
function handleClick() {
console.log("直接更新");
setTimeout(() => {
setState(state + 1)
}, 2000);
}
// 函数式更新
function handleClickFn() {
console.log("函数式更新");
setTimeout(() => {
setState((prevState) => {
return prevState + 1
})
}, 2000);
}
return (
<div>
state: {state}
<br />
<button onClick={handleClick}>直接更新</button>
<button onClick={handleClickFn}>函数式更新</button>
</div>
);
};
上面代码执行效果:
在图中 两种更新方式都点击了 5 次, 理想状态下 state 的值 2+5 应该是 7。但是 直接更新 state 的值停留在了 3 ,只有 函数式更新 的值才是正确的。
这是因为....
函数式更新:
set 接收一个函数,这个函数接收一个参数(prevState),这个参数的返回值永远是上一次最新的值,
因为函数式更新会将这次更新的值依次传递给下一次的函数式更新,所以这里得到的值是最新的。
直接更新:
每一次更新都是一个闭包(函数式更新也是)先记住这个。当我们快速点击时创建 5 个定时器,注意这个定时器时在 state 为 2 的闭包中时候创建的,所以此时它 5 个定时器 中 set接收的参数都是 state + 1 也是 3,它并不会像函数式更新一样依次传递下去 。5 次更新都是 3 ,React 会进行浅比较所以相当于只更新了一次
总结:
-
直接更新: 直接传入新的 state 值即可。适用于与返回的新值与旧值不存在依赖关系 -
函数式更新:传入一个函数 用该函数的返回值进行更新。适合用于旧值和新值有关系
最后
如果你对浅比较不太理解或者想深入一下 useSstate 可以看一下我上一篇的文章