React中函数调用相互影响:Roll按钮触发标签显隐异常的原因与解决
问题原因与解决方案:点击Roll按钮导致标签显隐异常
问题原因
- 组件每次渲染时,
shouldLabelBeVisible()都会重新执行,调用d6()生成新的随机值,以此判断标签的显隐状态。 - 点击Roll按钮会触发
setDieRollResult更新状态,进而导致组件重新渲染。此时shouldLabelBeVisible会再次执行,重新计算显隐状态,这就造成了标签随按钮点击随机切换状态的问题。 - 核心问题是:你把标签的显隐逻辑写成了渲染时的动态计算,而非初始化时的一次性状态,没有对这个状态进行持久化存储。
解决方法
要让标签的显隐状态只在组件首次加载时确定一次,后续不再随组件重新渲染改变,有两种常见实现方式:
方式一:使用useState持久化初始状态
通过useState的初始化函数形式,仅在组件首次挂载时计算一次显隐状态:
export default function App() { const [dieRollResult, setDieRollResult] = useState<number>(0); // 仅在组件首次挂载时计算标签显隐状态 const [labelVisibility, setLabelVisibility] = useState(() => { const d6 = () => Math.floor(Math.random() * 6) + 1; return d6() <= 3 ? "visible" : "hidden"; }); const d6 = () => Math.floor(Math.random() * 6) + 1; return ( <Stack> <Typography visibility={labelVisibility}>hello</Typography> <Typography>{dieRollResult}</Typography> <Button onClick={() => { setDieRollResult(d6()); }} > Roll </Button> </Stack> ); }
方式二:使用useMemo缓存计算结果
利用useMemo配合空依赖数组,确保显隐状态仅计算一次:
export default function App() { const [dieRollResult, setDieRollResult] = useState<number>(0); const d6 = () => Math.floor(Math.random() * 6) + 1; // 空依赖数组确保仅在组件首次渲染时计算 const labelVisibility = useMemo(() => { return d6() <= 3 ? "visible" : "hidden"; }, []); return ( <Stack> <Typography visibility={labelVisibility}>hello</Typography> <Typography>{dieRollResult}</Typography> <Button onClick={() => { setDieRollResult(d6()); }} > Roll </Button> </Stack> ); }
说明
两种方式都能实现需求,其中useState的方式更直观,明确表示这是一个需要持久化的状态;useMemo则适合处理纯计算的缓存场景。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

