I am trying to build a bar chart from some statistical data using d3 and react. I am passing statistical data as data
prop, and then in useEffect for deps data
, I am calling createScales
to get xscale and yscale respectively, and setting them up in state variables scaleX
and scaleY
, respectively. But when I run useEffect on deps [scaleX,scaleY]
,
there typeof
prints undefined.
Pasting code snippet :-
function BarChart({
data = [],
barWidth = 14
}) {
const createScales = () => {
const _xScale = d3.scaleBand()....
const _yScale = d3.scaleLinear()....
console.log(typeof _xScale, typeof _yScale, " scales ordered") //printed as line 29 in console below
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") //printed as line 107
console.log(typeof x, typeof y, "scales from order") //printed as line 112
setScalX(x)
setScalY(y)
}, [data])
useEffect(() => {
console.log("useEffect called ", typeof scaleX, typeof scaleY) //printed as line 118
const [xAxisCall, yAxisCall] = createAxes()
if (xAxisCall && yAxisCall) {
{{chartDrawing logic}}
}
}, [scaleX, scaleY])
}
The console prints are as follows => x, y are functions inside createScales()
and these are set in state on data
change (112th line), but in useEffect
for scaleX
and scaleY
we get their typeof
as undefined. Pls note that i am not callin setScalX or setScalY anywhere else in component, is it some sideEffect of d3 ? :-
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
CodePudding user response:
This is an unfortunate and confusing issue when passing a function to be stored in state. When the setX
state updater function is passed a function it is interpreted to be an updater function, and when the React state update is processed is invoked and the function's return value is returned as the state's next value. In this case it seems the x
and y
functions are void returns.
To resolve, pass a function that returns the x
and y
functions you want to store in state.
Example:
useEffect(() => {
const [x, y] = createScales();
setScalX(() => x);
setScalY(() => y);
}, [data]);