Hello again, I decided to post another problem I found.
I implemented the logic discussed here in our real application which uses React.
Upon changing the reference data in a parent component, the data is updated in Flexmonster.
But whenever the data is changed, we're getting the following error from Flexmonster in the developer console:
Uncaught TypeError: Cannot read properties of null (reading 'element')
at new k (flexmonster.full.js:99:1)
at h.Fe (flexmonster.full.js:1572:1)
at flexmonster.full.js:1561:1
k @ flexmonster.full.js:99
Fe @ flexmonster.full.js:1572
(anonyme) @ flexmonster.full.js:1561
requestAnimationFrame (asynchrone)
requestAnimationFrame @ flexmonster.full.js:149
u.$n.load.ON @ flexmonster.full.js:1559
load @ flexmonster.full.js:86
h @ flexmonster.full.js:1559
k @ flexmonster.full.js:2365
PivotApi @ flexmonster.full.js:2383
(anonyme) @ flexmonster.full.js:2393
(anonyme) @ index.js:1
invokePassiveEffectCreate @ react-dom.development.js:23487
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
flushPassiveEffectsImpl @ react-dom.development.js:23574
unstable_runWithPriority @ scheduler.development.js:468
runWithPriority$1 @ react-dom.development.js:11276
flushPassiveEffects @ react-dom.development.js:23447
(anonyme) @ react-dom.development.js:23324
workLoop @ scheduler.development.js:417
flushWork @ scheduler.development.js:390
performWorkUntilDeadline @ scheduler.development.js:157
The implementation of the component looks roughly as below (the actual code is more complex).
The code is actually more complex, and may contain errors, but my first question here would be more to know how to debug the problem on my side. And to find out if this
import React, { useEffect, useRef, useState } from 'react';
import { FlexmonsterReference, Pivot } from 'react-flexmonster/hooks';
// Illustration - Actual code may differ
const MyComponent: React.FC<any> = ({
licenseKey,
data,
config,
localization,
}) => {
const flexmonsterRef = useRef<FlexmonsterReference>(null);
const [report, setReport] = useState<any>([]);
useEffect(() => {
const x = {
...config,
localization,
dataSource: { data },
}
setReport(x);
}, [data, config, localization]);
// none of these are triggered
const handleDataError = (params: any) => console.log('dataerror', params);
const handleLocalizationError = () => console.log('localizationerror');
const handleQueryError = () => console.log('queryerror');
return (
<Pivot
ref={flexmonsterRef}
licenseKey={licenseKey}
report={report}
dataerror={handleDataError}
localizationerror={handleLocalizationError}
queryerror={handleQueryError}
/>
);
};
Hello,
Thank you for reaching out to us.
We haven't managed to reproduce the described issue on our side. Could you please provide us with the sample project where the reported issue can be reproduced? It will help us to continue the investigation.
Looking forward to hearing from you.
Kind regards,
Nadia
Hello, Sophie,
As a follow-up to our previous answer, please check the suggestion below.
In your code sample, there's importing from react-flexmonster/hooks
:
import { FlexmonsterReference, Pivot } from 'react-flexmonster/hooks';
We suggest importing instead:
import * as Pivot from 'react-flexmonster';
Please let us know if such an approach would work for your case. Looking forward to your response.
Kind regards,
Nadia
Hello Nadia,
This didn't resolve the problem.
I looked at our code, and I think the reason why the initial developer (now gone) imported from `react-flexmonster/hooks` is likely that he wanted to import FlexmonsterRefefence
to be used in `const flexmonsterRef = useRef<FlexmonsterReference>(null);`
After changing to main FlexmonsterReact.Pivot
, FlexmonsterReference`
doesn't work anymore to type the ref (I used any
for now).
If you think that not importing from hooks is preferable, we'll do it anyway.
Hello again.
I may have found one of the sources of the problem, but that doesn't solve everything, and I'll explain, because I'd like to get to the bottom of it and make sure that we do things properly.
So, back to my example, the problem I found is that a key
prop was added to the Pivot
to explicitly force React to recreate the component.
import * as FlexmonsterReact from 'react-flexmonster';
const MyComponent: React.FC<any> = (data, config) => {
const flexmonsterRef = useRef<any>(); // was: useRef<FlexmonsterReference>
return <FlexmonsterReact.Pivot
key={random()} // Important: Do not remove
report={getReport(computeReport(data, config)}
ref={flexmonsterRef}
... />
}
Removing the key
` seems to solve the problem, but it came with a warning and a fat comment from the initial developer (now gone):
Flexmonster is providing a React wrapper for their product. Under the hood, they use a global instance of their library. I noticed they create and dispose their instance automatically when you render the component.
There is a problem when you re-render the same component too quickly. They might kill their global instance between 2 renders and you'll end up not having access to their instance (remember all random error we had with wdr "this.q8 is undefined"...)
The solution that was implemented was to:
shouldComponentUpdate
` React Hooks - How do I implement shouldComponentUpdate?If memoizing may sometimes be necessary (point 1, equivalent to shouldComponentUpdate
`), debouncing starts looking like a hack, and forcing a random key definitely calls for scrutiny, as forcing a React component to be rerendered is costly, but also doesn't guarantee that the underlying non react flexmonster instance would indeed be removed / recreated as we'd like.
Pivot
(looking at the exposed code, I agree that it's not clear to me)?
getData()
`I think). If behind the scene a single instance of Flexmonster is used, could it be that some config spilled from that global instance into our pages and somehow "corrupt" some of our reports by reporting data from a previous report?So, again, I apologize if I didn't expose all our internal "cuisine", but as I mentioned above, I'd rather get to the bottom of it to ensure that our application runs smoothly without risking data corruption.
Another quick update to mention that I'm continuing the investigation on my side, as some of my previous conclusions may have been a bit too hasty. Right now, the debouncing I mentioned seems like it might be the culprit, but I will come back to you.
Hello,
Thank you for the detailed information.
Please check the answers below:
- That is why 2 distinct <Pivot> components can coexist in the same application without any harm
We hope it helps. You are welcome to write to us in case further questions arise.
Kind regards,
Nadia
This question is now closed