使用React与D3构建柱状图时,useEffect中scaleX/scaleY状态显示undefined
问题
我正在尝试使用D3和React基于统计数据构建柱状图。将统计数据作为data属性传入后,在依赖data的useEffect中调用createScales获取x轴和y轴比例尺,再将它们存入状态变量scaleX和scaleY。但在依赖[scaleX, scaleY]的useEffect中执行时,typeof打印结果为undefined。
代码片段:
function BarChart({ data = [], barWidth = 14 }) { const createScales = () => { const _xScale = d3.scaleBand().... const _yScale = d3.scaleLinear().... console.log(typeof _xScale, typeof _yScale, " scales ordered") // 控制台中对应第29行 return [_xScale, _yScale] } const [scaleX, setScalX] = useState(undefined) const [scaleY, setScalY] = useState(undefined) useEffect(() => { const [x, y] = createScales() console.log(typeof scaleX, typeof scaleY, "scales before change when change scale called") // 控制台中对应第107行 console.log(typeof x, typeof y, "scales from order") // 控制台中对应第112行 setScalX(x) setScalY(y) }, [data]) useEffect(() => { console.log("useEffect called ", typeof scaleX, typeof scaleY) // 控制台中对应第118行 const [xAxisCall, yAxisCall] = createAxes() if (xAxisCall && yAxisCall) { {{图表绘制逻辑}} } }, [scaleX, scaleY]) }
控制台输出:
VM2278:236 bar-chart.js:29 function function scales ordered bar-chart.js:107 undefined undefined scales before change when change scale called bar-chart.js:112 function function scales from order bar-chart.js:118 useEffect called undefined undefined bar-chart.js:29 function function scales ordered bar-chart.js:107 undefined undefined scales before change when change scale called bar-chart.js:112 function function scales from order bar-chart.js:118 useEffect called undefined undefined
疑问:createScales()返回的x、y都是函数,且在data变化时尝试存入状态,但依赖scaleX和scaleY的useEffect中它们的类型仍是undefined。我没有在组件其他地方调用setScalX或setScalY,这是不是D3的副作用导致的?
解答
- 核心问题是状态更新函数的拼写错误:你在
useState定义时,把状态更新函数的名字写错了。- 定义的是
const [scaleX, setScaleX] = useState(undefined),但调用时写成了setScalX(x)(少了字母e); - 同理,
const [scaleY, setScaleY] = useState(undefined),调用时写成了setScalY(y)。
- 定义的是
- 因为调用了错误的更新函数,React并没有正确更新
scaleX和scaleY的状态值,它们始终保持初始的undefined,所以第二个useEffect中打印的结果自然是undefined。 - 这和D3没有任何关系,完全是React状态更新的拼写失误。
解决方法:修正状态更新函数的拼写,把setScalX改为setScaleX,setScalY改为setScaleY即可:
useEffect(() => { const [x, y] = createScales() console.log(typeof scaleX, typeof scaleY, "scales before change when change scale called") console.log(typeof x, typeof y, "scales from order") // 修正拼写错误 setScaleX(x) setScaleY(y) }, [data])
内容的提问来源于stack exchange,提问作者Harit Saxena
相关产品推荐
相关产品推荐

