浅谈 setState() 和 useState() 的对比

二者参数对比

  • setState( updater [,callback] ) 
    • updater:object/function - 用于更新数据
    • callback:function - 用于获取更新后最新的 state 值
  • useState(initState)
    • const [ state , setState ] = useState(initState)
      • state:状态
      • setState(updater) :修改状态的方法
        • updater:object/function - 用于更新数据
      • 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()更新引用需要手动浅合并

 

  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一生只爱婉儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值