-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LG-4662: Fix bundle size + other charts improvements #2611
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: 68595ff The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
charts/core/src/Echart/useEchart.ts
Outdated
const withInstanceCheck = <T extends (...args: Array<any>) => void>( | ||
fn: T, | ||
) => { | ||
return (...args: Parameters<T>) => { | ||
if (!echartsInstance) { | ||
console.error('Echart instance not initialized'); | ||
return; | ||
} | ||
fn(...args); | ||
}; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went back and forth on whether this should actually wait for an instance. In theory, we could store a promise in a ref, and make all of the methods asynchronous. I ultimately decided not to and instead essentially do nothing if the instance doesn't exist yet. But would be curious to hear other thoughts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little confused why this is necessary. Is it just for the error logging?
Unless I'm missing something, the optional chain check (e.g. L114) should catch if the echartsInstance
singleton is undefined/null.
Edit: I guess it's useful to fully abort if the instance isn't defined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this were to wait for the instance, that would mean all the instance methods (like addSeries
) would all be async?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Edit: I guess it's useful to fully abort if the instance isn't defined
That's correct. This is used as a higher order function to wrap any function that relies on the existence of an instance. This is an extraction of duplicate logic that was being used inline in each of those methods, attempting to handle the case where it doesn't exist yet gracefully.
If this were to wait for the instance, that would mean all the instance methods (like addSeries) would all be async?
That's correct. It would basically wrap the given function in a promise, converting it to an async function that's capable of being awaited, so instead of just (almost) silently ignoring this case, the execution wouldn't occur until the instance did exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fwiw, I don't think I like this. I think the interface of just exposing some way to determine readiness is fine.
Size Change: +6.67 kB (+0.48%) Total Size: 1.4 MB
ℹ️ View Unchanged
|
const { theme } = useDarkMode(); | ||
|
||
useEffect(() => { | ||
if (!chart.ready) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be misunderstanding how echarts works, but why can't we check if chart
is defined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chart
in this case is an instance of ChartInstance
. In theory, that's actually always defined even when the echart
hasn't been initialized. We could check if chart._echartsInstance
is defined, but I just added chart.ready
as a helper boolean to avoid having to interact directly with the instance outside of useEchart
. Does that make sense?
const [echartsInstance, setEchartsInstance] = useState<any>(null); // has to be any since no types exist until import | ||
const [error, setError] = useState<EChartsInstance['error']>(null); | ||
const [ready, setReady] = useState<EChartsInstance['ready']>(false); | ||
const [options, setOptions] = useState<EChartsInstance['options']>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remind me, why do we need to keep track of options in state if we can access them via echartsInstance.options?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want it more easily accessible from this hook's return object, could we just have
const options = useMemo(() => echartsInstance.options, [...]) // or whatever the correct property is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think at one point early on I was tying into changes in order to trigger updates. Since this is no longer the case, I think this is a really good point. Will look into removing this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay I dug into this more and remember why we were holding a copy of the options. This is what made it possible to batch updates. Since we debounce calls to echartsInstance.setOption()
via setEchartOptions
, when additional updates occur in short order, they don't have an accurate copy of the current options since echartsInstance.getOption()
is not necessarily up to date yet.
I know there was some initial disagreement regarding whether this batching was necessary. I tried to run some tests rendering a chart with 100 lines. With batching, the chart appeared after about 4000ms. Without batching, it didn't appear until after the profiler stopped recording which seemed to be around 6000ms. I'm not 100% sure what caused this but I am under the impression that each additional update is supposed to cause a repaint of the canvas, so it would be 1 repaint vs 100+ repaints. Though, I have no idea if that's what caused this, it could be something totally unrelated, at least withe current implementation it caused an inherent slowdown.
Happy to discuss further of course if there are other ideas, but just going to leave as is for now.
const mockEchartsInstance = { | ||
setOption: jest.fn(), | ||
dispose: jest.fn(), | ||
resize: jest.fn(), | ||
on: jest.fn(), | ||
off: jest.fn(), | ||
dispatchAction: jest.fn(), | ||
group: null, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥
updateChartOptions: (newOptions: Partial<ChartOptions>) => void; | ||
addChartSeries: (series: SeriesOption) => void; | ||
removeChartSeries: (name: string) => void; | ||
chart: ChartInstance; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could this be undefined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ChartInstance
, the object with the instance methods, I don't believe should be, but props like ChartInstance._echartsInstance
could be null
.
44436b4
to
eea4d45
Compare
1bf408e
to
68595ff
Compare
✍️ Proposed changes
offsetWidth
bug.useEchart
hook.ChartInstance
in full via theChartProvider
instead of individual methods.🎟 Jira tickets:
offsetWidth
erroruseChart
✅ Checklist
For bug fixes, new features & breaking changes
yarn changeset
and documented my changesFor new components
🧪 How to test changes