二者参数对比
- setState( updater [,callback] )
- updater:object/function - 用于更新数据
- callback:function - 用于获取更新后最新的 state 值
- useState(initState)
- const [ state , setState ] = useState(initState)
- state:状态
- setState(updater) :修改状态的方法
- updater:object/function - 用于更新数据
- initState:状态的初始值
- const [ state , setState ] = useState(initState)
setState()使用注意事项
- setState()
- 构造函数是唯一建议给 this.state 赋值的地方
- 不建议直接修改 state 的值,因为这样不会重新渲染组件
- 自动进行浅合并(只会合并第1层)
- 由于 setState() 异步更新的缘故,依赖 state 旧值更新 state 的时候建议采用传入函数的方式
1、构造函数是唯一建议给 this.state 赋值的地方
constructor(props) {
super(props);
this.state = {
comment: "hi"
};
}
2、更新写法对比
this.state.comment = 'Hello'; // 错误写法
this.setState({comment: 'Hello'}); // 正确写法
3、浅合并演示
this.setState({age:10});
//实际上会转化为如下的形式
this.state = {
...this.state,
age:10
}
4、使用 state 旧值更新的建议写法
this.setState({ //错误写法
counter: this.state.counter + this.props.increment,
});
this.setState((state, props) => ({ //正确写法
counter: state.counter + props.increment
}));
- setState() 的异步问题
- setState() 在绝大多数情况下都是异步操作,更新 state 后无法直接获取最新的 state 值
this.setState({name:'ls'})
console.log(this.state.name) //打印的是之前的旧值,而非'ls'
解决方案:可在第2个参数回调函数中获取最新 state 值
this.setState({name:'ls'},
() => {
console.log(this.state.name); //打印'ls'
})
useState()使用注意事项
- useState()
- 可以自定义命名
- 可以使用多个useState()
- 不具备自动浅合并的效果
1、自定义命名演示
const [count, setCount] = useState(1);
2、可以使用多个useState(),之间相互独立
const [age, setAge] = useState(1);
const [name, setName] = useState('李芮依');
3、不具备自动浅合并效果
const [obj, setObj] = useState({ a: 1, b: 2 });
setObj({ //引用类型需要手动进行浅合并
...obj,
a: obj.a + 1
})
- useState() 中类似setState() 异步的问题
- 调用 setState() 后组件不会立刻更新,无法立刻获取到最新的 state 值
const [count, setCount] = useState(1);
setCount(count + 1);
console.log(count) //setCount()后直接打印出的是旧数据
解决办法:由于useState()获取的setState()不支持第2个参数,可以通过useEffect来解决此问题
useEffect(() => {
console.log(count);
}, [count]);
- 思考领悟:为什么叫做 useState 而不是 createState ?
- const [ state , setState ] = useState( initVal )
- 因为 create 的描述不准确,state 只有在组件首次渲染时才会被创建并赋予初始值 initVal。当函数组件更新时,虽然会重新执行函数组件中的每一行代码,但是 useState 底层做了特殊的处理,使得每次更新不会使用 initVal 来创建新的 state ,而是返回给我们当前的 state
对比与总结
1、二者更新数据时,第一个参数都可以传入函数
this.setState((state, props) => ({ //setState()
counter: state.counter + props.increment
}));
setCount(count => count + 1); //useState()
2、setState()可以在第2个参数传入回调, useState()没有第2个参数
this.setState(
{count: this.state.count + 1},
() => console.log(this.state.count) //可以通过第2个回调函数获取最新的state值
);
PS:函数式组件中可以通过 useEffect() 来获取最新的 state
3、setState() 自动具备浅合并功能,useState()更新引用需要手动浅合并