You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React的Piano组件useEffect初始渲染不运行 仅窗口resize时触发

问题根因
  • 初始渲染阶段DOM未完成挂载,直接在组件顶层执行const svgEl = d3.select(svgRef.current)时,svgRef.current为null,提前保存的svgEl是空选择集,初始执行useEffect时无法操作DOM完成渲染。
  • 后续新增的空依赖useEffect依然使用了顶层提前声明的空svgEl,因此无法生效。窗口调整时组件重新渲染,此时svgRef已经绑定了DOM元素,重新赋值的svgEl有效,渲染逻辑才会正常执行。
修复方案

将SVG元素的获取逻辑移到useEffect内部,保证每次执行渲染逻辑时都能拿到有效的DOM引用,修正后的代码如下:

const svgRef = React.useRef(null);

const { width } = useWindowDimensions();
const height = width / 4;

const keyData = generateKeyData(88, width);

React.useEffect(() => {
  const svgEl = d3.select(svgRef.current);
  // 增加边界判断,避免初始宽度无效时报错
  if (svgEl.empty()) return;
  svgEl.selectAll("*").remove();
  generatePianoNode(svgEl, keyData);
}, [keyData]);

return (
  <svg ref={ svgRef } width={ width } height={ height } />
);
改动说明
  • 移除了组件顶层的svgEl声明,改在useEffect内部动态获取,确保DOM已挂载、ref存在有效值
  • 移除了依赖项中不稳定的svgEl变量,仅保留keyData作为依赖即可:svgRef是React创建的稳定引用,不需要加入依赖列表
  • 增加非空判断,兼容useWindowDimensions初始返回无效宽度的边界场景

内容的提问来源于stack exchange,提问作者Batın Evirgen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 19:45:05