Closed fastrocket closed 5 years ago
The client shouldn't care what Rx API use in the back-end, as long as it provides data in the expected format. This line here:
Averages.js:26 Uncaught TypeError: Cannot read property 'length' of null
Is this your React component? it seems that it expects an array, but is given null. Remember, on initial render, the component hasn't received the state from the server yet, so it's important to define initial client state to a proper (empty) array object.
My Averages.js is an exact copy of Traffic.js (I forgot to capture the errors with stock demo). Here are the errors from using an unchanged Traffic.js:
Download the React DevTools for a better development experience: https://fb.me/react-devtools Utils.js:196 Information: Normalizing '/dotnetify' to 'http://localhost:50263/dotnetify'. Utils.js:196 Information: WebSocket connected to ws://localhost:50263/dotnetify?id=5PjSCZAnS9dLIhAB_E29_g client.js:92 [HMR] connected Traffic.js:26 Uncaught TypeError: Cannot read property 'length' of null at Traffic (Traffic.js:26) at updateFunctionalComponent (react-dom.development.js:8317) at beginWork (react-dom.development.js:8980) at performUnitOfWork (react-dom.development.js:11814) at workLoop (react-dom.development.js:11843) at HTMLUnknownElement.callCallback (react-dom.development.js:100) at Object.invokeGuardedCallbackDev (react-dom.development.js:138) at invokeGuardedCallback (react-dom.development.js:187) at replayUnitOfWork (react-dom.development.js:11318) at renderRoot (react-dom.development.js:11885) react-dom.development.js:9643 The above error occurred in the
component: in Traffic (created by Dashboard) in div (created by Dashboard) in div (created by Dashboard) in div (created by Dashboard) in MuiThemeProvider (created by Dashboard) in Dashboard Consider adding an error boundary to your tree to customize error handling behavior. Visit https://fb.me/react-error-boundaries to learn more about error boundaries. logCapturedError @ react-dom.development.js:9643 react-dom.development.js:12431 Uncaught TypeError: Cannot read property 'length' of null at Traffic (Traffic.js:26) at updateFunctionalComponent (react-dom.development.js:8317) at beginWork (react-dom.development.js:8980) at performUnitOfWork (react-dom.development.js:11814) at workLoop (react-dom.development.js:11843) at renderRoot (react-dom.development.js:11874) at performWorkOnRoot (react-dom.development.js:12449) at performWork (react-dom.development.js:12370) at performSyncWork (react-dom.development.js:12347) at requestWork (react-dom.development.js:12247)
Steps to repro:
Traffic = Observable
.Interval(TimeSpan.FromMilliseconds(50))
.StartWith(0)
.Select(_ => _random.Next(200, 300))
.Buffer(TimeSpan.FromMilliseconds(1000))
.Where(x => x.Any()).Select(x => x.ToArray());
var sub = Traffic.Subscribe(x =>
{
Console.WriteLine($"x has {x.Length} entries");
});
With that code, the initial Traffic value is null, that's why the client breaks. You need to add a check on the component, and only render the component if the incoming value isn't null (or replace the value with an empty array).
Thanks for the pointer! I was able to fix the problem by adding the null checks in Traffic.js, and it occurred to me I could append
.StartWith(new[] { 0 });
at the end of the Observable initialization in MockLiveDataServices.cs, and either solution worked.
I thought the initial setting of
this.state = {
Traffic: [],
in Dashboard.js would take care of the first value? Answering my own question, here, it was nulls, not an empty initial array.
So it seems that this code:
// Regulate data update interval to no less than every 200 msecs.
_subscription = Observable
.Interval(TimeSpan.FromMilliseconds(200))
.StartWith(0)
.Subscribe(_ => PushUpdates());
sends nulls to React if any Observable has not emitted any values?
Anyway, thanks again! This has been a fun crash course in Rx and React.
So I made one test change to the demo project to the Traffic widget mock data source:
I can confirm that the test subscription above is seeing an array of int.
But the javascript console shows these errors when trying to display the UI:
I've gone through many permutations including removing the Where() check, the ToArray(), etc. to no avail. Any help appreciated! I'd like to use Buffer() if possible. I'm currently having to use the subscriber to dump the array into another observable which isn't elegant.