useState()
useState()基础语法
useState:React Hook函数之一,目的是在函数组件中使用状态,并且后期基于状态的修改,可以让组件更新
let [num,setNum] = useState(initialValue);
- 执行useState,传递的initialValue是初始的状态值
- 执行这个方法,返回结果是一个数组:[状态值,修改状态的方法]
- num变量存储的是:获取的状态值
- setNum变量存储的是:修改状态的方法
- 执行 setNum(value)
- 修改状态值为value
- 通知视图更新
函数组件「或者Hooks组件」不是类组件,所以没有实例的概念「调用组件不再是创建类的实例,而是把函数执行,产生一个私有上下文而已」,再所以,在函数组件中不涉及this的处理!!
Hooks组件:
const Demo = function Demo() {
let [num, setNum] = useState(0);
const handle = () => {
setNum(num + 10);
};
return <div className="demo">
<span className="num">{
num}</span>
<Button type="primary" size="small" onClick={
handle}>新增</Button>
</div>;
};
纯函数组件:静态组件
// 纯函数组件:静态组件
const Demo = function Demo() {
let n = 0;
return <div className="demo">
<span className="num">{
n}</span>
<Button type="primary" size="small" onClick={
() => {
n += 10;
console.log(n);
}}>新增</Button>
</div>;
};
类组件:动态组件
// 类组件:动态组件
class Demo extends React.Component {
state = {
n: 0
};
handle = () => {
let {
n } = this.state;
this.setState({
n: n + 10
});
};
render() {
let {
n } = this.state;
return <div className="demo">
<span className="num">{
n}</span>
<Button type="primary" size="small" onClick={
this.handle}>新增</Button>
</div>;
}
}
useState()底层处理机制
函数组件的每一次渲染(或者是更新),都是把函数(重新)执行,产生一个全新的“私有上下文”!
- 内部的代码也需要重新执行
- 涉及的函数需要重新的构建{这些函数的作用域(函数执行的上级上下文),是每一次执行DEMO产生的闭包}
- 每一次执行DEMO函数,也会把useState重新执行,但是:
- 执行useState,只有第一次,设置的初始值会生效,其余以后再执行,获取的状态都是最新的状态值「而不是初始值」
- 返回的修改状态的方法,每一次都是返回一个新的
const Demo = function Demo() {
let [num, setNum] = useState(0);
const handle = () => {
setNum(num + 10);
};
return <div className="demo">
<span className="num">{
num}</span>
<Button type="primary" size="small" onClick={
handle}>新增</Button>
</div>;
}
闭包作用域:
实现useState重新执行相关要求的伪代码:
var _state;
function useState(initialValue) {
if (typeof _state === "undefined") {
_state = initialValue
};
var setState = function setState(value) {
_state = value;
// 通知视图更新
...
};
return [_state, setState];
}
let [num1, setNum] = useState(0); //num1=0 setNum=setState 0x001
setNum(100); //=>_state=100 通知视图更新
// ---
let [num2, setNum] = useState(0); //num2=100 setNum=setState 0x002
小问题:num打印几?-利用上述原理很容易解释:
const Demo = function Demo() {
let [num, setNum] = useState(0);
const handle = () => {
setNum(100);
setTimeout(() => {
console.log(num); // 0
}, 2000);
};
return <div className="demo">
<span className="num">{
num}</span>
<Button type="primary" size="small" onClick={
handle}>新增</Button>
</div>;
};
useState()细节处理
useState创建、使用多个状态注意事项
执行一次useState:把需要的状态信息都放在对象中统一管理
- 执行setState方法的时候,传递的是啥值,就把状态“整体”改为啥值
setState({
supNum: state.supNum + 1
})
=> 把状态值修改为 {supNum:11} ,oppNum成员就丢失了
=> 并不会像类组件中的this.setState一样,不支持部分状态的更新- 应该改为以下的处理方案
se