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

React中给Div添加子元素时useRef的current属性仍返回undefined问题求助

问题原因
  • 你直接在组件渲染逻辑中调用drawChart,此时组件还没完成DOM挂载,ref.current还没有指向实际的DOM节点,自然会返回undefined或null
  • 你同时维护了回调ref绑定的refState和useRef生成的ref两套引用,没有必要,存在取值不一致的风险
  • 没有做旧节点清理逻辑,后续如果数据更新重新绘制,会出现柱子重复堆叠的问题
修正方案

直接用useRef绑定DOM节点,把绘制逻辑放到useEffect中,确保DOM挂载完成后再执行绘制即可,修改后的完整代码如下:

import React from "react";
import { useRef, useEffect } from "react";
import "./ExpenseFilter.css";

const ExpenseFilter = (props) => {
  const values = [100, 100, 340, 320, 500, 50, 45, 385, 95, 120, 90, 20];
  const chartRef = useRef(null);

  const drawChart = (data, padding) => {
    // 加非空判断,避免DOM未挂载时报错
    if (!chartRef.current) return;
    const max = Math.max.apply(Math, data);
    const chart = chartRef.current;
    // 清空旧节点,避免重复绘制
    chart.innerHTML = '';
    const barwidth =
      (chart.offsetWidth - (values.length - 1) * padding - data.length * 10) /
      data.length;
    let left = 0;
    for (let i in data) {
      let newbar = document.createElement("div");
      newbar.setAttribute("class", "bar");
      newbar.style.width = barwidth + "px";
      newbar.style.height = (data[i] / max) * 100 + "%";
      newbar.style.left = left + "px";
      chart.appendChild(newbar);
      left += barwidth + padding + 10;
      props.OnChangeDiv(newbar);
    }
  };

  // DOM挂载完成后或数据变更时才执行绘制
  useEffect(() => {
    drawChart(values, 15);
  }, [values]);

  return (
    <div className="wrapper1">
      <div className="select" tabIndex="1">
        <input
          className="selectopt"
          name="test"
          type="radio"
          id="opt1"
          checked
        />
        <label htmlFor="opt1" className="option">
          2019
        </label>
        <input className="selectopt" name="test" type="radio" id="opt2" />
        <label htmlFor="opt2" className="option">
          2020
        </label>
        <input className="selectopt" name="test" type="radio" id="opt3" />
        <label htmlFor="opt3" className="option">
          2021
        </label>
        <input className="selectopt" name="test" type="radio" id="opt4" />
        <label htmlFor="opt4" className="option">
          2022
        </label>
        <input className="selectopt" name="test" type="radio" id="opt5" />
        <label htmlFor="opt5" className="option">
          2023
        </label>
      </div>
      {/* 直接把ref绑定到DOM节点 */}
      <div
        id="chart"
        ref={chartRef}
      ></div>
    </div>
  );
};

export default ExpenseFilter;
额外优化建议

如果不想手动操作DOM,也可以用React声明式的写法渲染柱子:把计算好的柱子样式存到数组里,直接在JSX中遍历生成对应div.bar元素即可,不需要手动操作appendChild,更符合React的开发规范。

内容的提问来源于stack exchange,提问作者Vidyadhar M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 21:45:02