joshp
joshp

Reputation: 826

Uncaught TypeError during ResizeObserver Call: chartObj.width is not a function

I'm following this example, using the following code

  // resizable chart function
  const callback = (chartObj: DCGraphicType) => () => {
    redrawChartNoTransitions(chartObj.width(null).rescale()); // @typeerror
  };

  // watch for resize and call callback when resize occurs
  React.useEffect(() => {
    new ResizeObserver(callback(chart)).observe(
      d3.select(div.current!).node()!
    );
  }, [chart]);

and getting this error:

ChartTemplate.tsx:77 Uncaught TypeError: chartObj.width is not a function
    at ResizeObserver.<anonymous> (ChartTemplate.tsx:77)
(anonymous) @ ChartTemplate.tsx:77

Note: the helper functions are

const restoreGetset = (property, value) => f => c => {
  if (Array.isArray(c)) c.forEach(restoreGetset(property, value)(f));
  else {
    const cs = c.children ? [c].concat(c.children()) : [c];
    const last = cs.map(c => c[property]());
    cs.forEach(ch => ch[property](value));
    f(c);
    cs.forEach(ch => ch[property](last));
  }
  return c;
};

// specifically, turn off transitions for a chart or charts
const noTransitions = restoreGetset("transitionDuration", 0);
// specifically, turn off transitions for a chart or charts and redraw
export const redrawChartNoTransitions = noTransitions(c => c.redraw());

This works on my local app (forced through the error), but I'd like to understand and get rid of it... Here's a Stackblitz with the error in place

Upvotes: 3

Views: 1935

Answers (1)

Gordon
Gordon

Reputation: 20130

I'm haven't learned Hooks yet, so I'm not sure exactly where in React it's coming from, but it seems that chart is an empty object when the page is initializing, and becomes valid later.

In your chartTemplate.tsx:

  React.useEffect(() => {
    new ResizeObserver(callback(chart)).observe(
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
      d3.select(div.current!).node()!
    );
  }, [chart]);

It's probably not the right place to fix this, but ignoring the blank object:

if (!Object.keys(chart).length) return;

gets it working.

Debugging using Chrome DevTools

In Chrome DevTools, show the browser console and click on the code link in the error.

Set a breakpoint on the offending line inside the callback, and notice that chart is an empty object the first time the line is hit, but if you continue it becomes valid.

Debugging using console.log()

Adding, on the line before the error,

console.log(chartObj);

produces the following output in the browser debug console:

debug output with trace

The empty object is printed twice, each time followed by the error. Then the instantiated chart object is printed twice with no error.

Upvotes: 2

Related Questions