useState神奇用法带来的思考

📒 事件的始末

最近因为入职新公司,接手了好多个业务。在上个月的某个需求里,遇到了类似下面的代码:

ts 复制代码
    // 在函数组件内部
    const foo = props.id || props.code
    const [val = foo, setVal] = useState(foo)

当看到这段代码的时候,无数问号在我的脑袋瓜周围盘旋。。。这代码为什么看着这么奇怪。。。然后我就想着,要不优化成正常人能看懂的代码?然后就有了下面的代码:

ts 复制代码
    const [val, setVal] = useState(props.id || props.code)

需求提测。测试完成。上线~。

心里暗暗高兴,又是功德圆满的一天。

就在今天,测试同学给我提了一个线上bug。然后经过三个小时的艰苦console,最后问题竟然定位在上面的代码里。然后我把代码恢复我修改之前,乖乖,真的可以了。。。再看之前的代码,竟然恍然大悟,这里面有不得了的东西:

  • useState(() => props.id || props.code) 是用props.id || props.codeval的初始值,后续如果props变化时,val是不会受到影响的。
  • [val = foo, setVal] = useState(foo)这里同样用props.id || props.code作初始值,但是当props.id || props.code变化时,且当 valundefined时,就会将更新后的foo值作为val的默认值。此时val是受到props变化影响的。

⏰ 针对上述的解决方案

如果是你,会怎么写这里的逻辑呢?

  1. 首先不管为什么props会变化?从可读性、可维护性上看,下面的实现是否更妥善:
ts 复制代码
const [val, setVal] = useState(props.id || props.code)

useEffect(() => {
    // props的状态变化要同步更新当前的state
    setVal(props.id || props.code)
}, [props.id, props.code])
  1. 如果再严谨一些,为什么props.id || props.code会由undefined之后才变成了有效值?如果这是一个父组件状态的初始化,是否可以在父组件内通过loading的状态来消除初始化的过程呢?

🤔 一些微不足道的思考

UI = f(state) 通常会用来表示数据与视图之间的关系。这里我突出的是状态维护对于页面展示的重要性。在维护状态(数据)时,要遵循一个重要原则:单一数据源 Single Source oF Truth。单一数据源能确保状态的变化是可以预测的、容易管理的,提升代码的可读性和可维护性。

上面的那个默认值的处理方式,其实隐藏了非单一数据源在逻辑里:val既可以从setVal变更而来,而可能在特殊情况下由foo赋值。而解决方案中的配合useEffect的方式,val的状态只能由setVal去改变。

我知道单一数据源原则 其实是适用更复杂场景下的数据维护。但是只有先做好组件层面的状态维护,才能一层层向上延展,维护好一个页面、甚至整个app的状态。

业务的场景渐千变万化,业务逻辑也可能异常复杂,但是要始终保持好的编码习惯和编码方式:

  1. 想清楚原理,再开始编码
  2. 复杂的逻辑、技巧性的编码要添加注释;没有注释的地方,变量名或者函数名要与业务意义挂钩,最好是别人能从中看出你想要做什么
  3. 学习类似单一数据源这样的原则,并应用到项目中,帮忙更好的组织代码

这样才能让我们和项目都走的更远。。。

相关推荐
UXbot3 小时前
UI设计工具推荐合集
前端·人工智能·ui
敲敲了个代码3 小时前
如何优化批量图片上传?队列机制+分片处理+断点续传三连击!(附源码)
前端·javascript·学习·职场和发展·node.js
@AfeiyuO4 小时前
Vue 引入全局样式scss
前端·vue·scss
光影少年4 小时前
flex布局和grid布局区别,实现两边固定布局中间自适应
前端·css3·web·ai编程
全栈测试笔记4 小时前
异步函数与异步生成器
linux·服务器·前端·数据库·python
EndingCoder4 小时前
配置 tsconfig.json:高级选项
linux·前端·ubuntu·typescript·json
木风小助理4 小时前
JavaStreamAPI的性能审视,优雅语法背后的隐形成本与优化实践
java·前端·数据库
white-persist5 小时前
轻松抓包微信小程序:Proxifier+Burp Suite教程
前端·网络·安全·网络安全·微信小程序·小程序·notepad++
敲敲了个代码7 小时前
多标签页强提醒不重复打扰:从“弹框轰炸”到“共享待处理队列”的实战
java·前端·javascript·面试·架构
不想上班只想要钱7 小时前
动态类名在 <swiper-slide 的复制项中没有起作用的解决方法
前端·vue.js