首页 注册 登录
V2EX = way to explore V2EX 是一个关于分享和探索的地方
现在注册 已注册用户请 登录
React
V2EX React

是否可以只对一个变量使用 useState,用来触发重新渲染即可,其他变量实时计算?

BruceXu · 2023 年 12 月 27 日 · 2574 次点击
这是一个创建于 745 天前的主题,其中的信息可能已经有所发展或是发生改变。

新手学习 React,最近刚发现如果有变量发生改变,不使用 useState 提供的 setXXX 也是可以的.

用 React 官方教程中的代码举例:

import { useState } from 'react';
export default function Counter() {
 const [number, setNumber] = useState(0);
 const [otherNumber, setOtherNumber] = useState(0);
 console.log("重新渲染")
 return (
 <>
 <h1>{number}</h1>
 <h1>{otherNumber}</h1>
 <button onClick={() => {
 setNumber(1);
 setOtherNumber(2);
 }}>+</button>
 </>
 )
}

效果是点击按钮,修改 number 和 otherNumber 的值,模拟实际使用中请求接口后需要修改多处变量显示的场景.

据我浅薄的理解,useState 此处应该是修改变量,并通知页面使用修改后的值重新渲染吧?打印的 log 确实也走了两遍.

所以可不可以这样:只对其中一个变量使用 useState(反正会重走 return 方法),剩下的变量就在 return 前面计算就行了:

import { useState } from 'react';
export default function Counter() {
 const [number, setNumber] = useState(0);
 let otherNumber = number == 1 ? 2:1;
 return (
 <>
 <h1>{number}</h1>
 <h2>{otherNumber}</h2>
 <button onClick={() => {
 setNumber(1);
 }}>+</button>
 </>
 )
}

这里的 let otherNumber = number == 1 ? 2:1;只是很简单的逻辑,实际使用中可能包含复杂的数据处理工作.

从运行效果来看,似乎也没啥问题......

这样岂不是可以把最外层的数据 rootData 做个 useState 就行了,里面各个组件从这个 rootData 里面拿.就是不知道对性能有没有影响了.

目前看的教程是 https://zh-hans.react.dev/learn,对 React 理解还不深,求大佬解惑,谢谢~

第 1 条附言 · 2023 年 12 月 27 日
具体说明一下实际场景吧:

实际使用中一个页面可能有很多 echarts 图表,这些图表数据来自于同一个接口.

所以我在想,是把接口返回的 data 做一个 useState,然后各个图表直接从里面取呢,还是每个图表都搞一个 useState,接口回来后挨个 setXXX 呢???

性能方面,大佬们能细说下吗...
19 条回复 2023年12月27日 14:39:54 +08:00
murmur
1
murmur 2023 年 12 月 27 日
以前我这么干过,react15 的年代,优化不明白了,我就给组件加个 key ,到时候把 key 改了重渲染,剩下的都不管了,愿意咋样咋样

意外的效果还不错,那个时候我们还做了 IE 兼容
AvilCore
2
AvilCore 2023 年 12 月 27 日 via Android
你这里的 othernumber 不是变量而是常量啊,eslint 会报错
这样实际上你的网页只有一个变量,商务逻辑需要的话这么做很正常
lisongeee
3
lisongeee 2023 年 12 月 27 日 ❤️ 1
> 打印的 log 确实也走了两遍

你确定不是开发模式下严格模式导致的?

---

你的第一个代码示例的两个 setXXX 处于一个同步任务下,按理说应该会被 react 合并为一个更新
344457769
4
344457769 2023 年 12 月 27 日
可以这样写,但是如果你在业务逻辑里直接改变 otherNumber 是不会重新渲染的
DKburNIng
5
DKburNIng 2023 年 12 月 27 日
这种简单代码可以,业务复杂了会 render 很多次,你这行三目就要执行很多很多次
foolnius
6
foolnius 2023 年 12 月 27 日
你的 otherNumber 定义依赖于 number ,我会考虑用 useMemo
Hoothin
7
Hoothin 2023 年 12 月 27 日
不如直接寫成 class + shouldComponentUpdate 了
paledream
8
paledream 2023 年 12 月 27 日
`这样岂不是可以把最外层的数据 rootData 做个 useState 就行了,里面各个组件从这个 rootData 里面拿.就是不知道对性能有没有影响了.`
1. 可以的
2. 对性能是有影响的
ZZITE
9
ZZITE 2023 年 12 月 27 日
应该根据你的需求来决定,这个 otherNumber 需不需要自主更新(主动的去 set 他的值)?如果只是完全依赖于 number 值得变化而变化,那么这样写没什么问题,也不需要 memo 比较,比较也需要开销的。
panxiuqing
10
panxiuqing 2023 年 12 月 27 日
`otherNumber` 只是依赖 `number` 的话就不应该定义两个 state 。
state 是应用外部通知内部状态变化的入口,effect 是应用内部状态变化需要通知外部时的入口。
只由内部状态计算而来的状态应该用 `useMemo`,不然无关状态导致的重渲染产生了重复计算。
vincenteof
11
vincenteof 2023 年 12 月 27 日 ❤️ 1
这是 react 推荐的,避免多余的 useState ,让数据自己流动
BruceXu
12
BruceXu
OP
2023 年 12 月 27 日
@lisongeee 我错了..确实是开发模式下导致的~~~~
BruceXu
13
BruceXu
OP
2023 年 12 月 27 日
@paledream 大佬,细说性能影响~~~
Yvette
14
Yvette 2023 年 12 月 27 日
1. React 18 开始已经默认自动 batch 状态更新了,你看到两次渲染的原因是官方文档的代码都会默认开 StrictMode
2. 绝大多数应用都不需要担心多一次渲染对性能带来的影响,如果有性能问题那肯定是本身代码写得有问题,所以学习初期不用过于担心渲染次数;可以简单粗暴地认为对**实际**性能没有任何影响
3. 没理解错的话你描述的从最外层传数据的方法确实是很多全局状态管理工具的原理,等你学到了 Context 应该就能清晰很多 https://react.dev/learn/passing-data-deeply-with-context
4. 你标题里描述的是一个官方推荐的 pattern ,能从现有的 state/props 计算得出的值直接在渲染时计算就好(同样,计算对实际性能的影响完全可以忽略不计,而且如果真的有影响也可以通过 memoization 解决),具体可以看看这个 https://react.dev/learn/choosing-the-state-structure#avoid-redundant-state 以及等你更熟悉一点之后看看这个 https://react.dev/learn/you-might-not-need-an-effect
BruceXu
15
BruceXu
OP
2023 年 12 月 27 日
@ZZITE
@panxiuqing
感谢两位大佬解惑.
不过关于 useMemo 似乎有不同意见...这个东西我还要细看一下,目前确实只用到 state 和 effect 这两个 hook.
BruceXu
16
BruceXu
OP
2023 年 12 月 27 日
@Yvette 感谢感谢..
那我就渲染时直接计算了,搞这么多 useState 还要挨个调用 setXXX 确实挺烦的.
codehz
17
codehz 2023 年 12 月 27 日 via iPhone
@xubingok useMemo 是给计算需要一定成本的用的,简单加减乘除甚至字符串连接都不需要。
我觉得你这个例子里用 setState 没有问题,但是扩展到更大项目里,如果每个子元素的更新都要触发 root 组件的更新的话,就有点问题了,这时候可以考虑引入第三方状态管理库来处理
冷知识好多第三方状态管理库也都是接入到 react 的 useState (或者更高级的 useSyncExternalStore )来处理,但是针对复杂嵌套状态做了优化,避免了"牵一发动全身"的问题,只会在用到状态的地方触发 setState (或者 sync external store 里的回调)
BruceXu
18
BruceXu
OP
2023 年 12 月 27 日
@codehz 谢谢.
BruceXu
19
BruceXu
OP
2023 年 12 月 27 日
@Yvette
我又看了一遍 https://zh-hans.react.dev/learn/choosing-the-state-structure#avoid-duplication-in-state
确实有提到这个用法,写得是真好啊~
大佬实在太实诚了,这个章节正好解答了我的问题~~~
再次感谢~
关于 · 帮助文档 · 自助推广系统 · 博客 · API · FAQ · Solana · 2768 人在线 最高记录 6679 · Select Language 创意工作者们的社区 World is powered by solitude VERSION: 3.9.8.5 · 35ms · UTC 14:28 · PVG 22:28 · LAX 06:28 · JFK 09:28
♥ Do have faith in what you're doing.

AltStyle によって変換されたページ (->オリジナル) /