-
Notifications
You must be signed in to change notification settings - Fork 530
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
Move redux and focusSpan up from VirtualizedTraceView #517
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Andrej Ocenas <[email protected]>
}); | ||
|
||
describe('mapDispatchToProps()', () => { | ||
it('creates the actions correctly', () => { | ||
expect(mapDispatchToProps(() => {})).toEqual({ | ||
expect(mapDispatchToProps(() => {})).toMatchObject({ |
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.
There are few more functions because of the usage of:
...((bindActionCreators(timelineActions, dispatch) as unknown) as TDispatchPropsTimelineViewer),
In the map dispatch see a comment there.
acknowledgeArchive, | ||
archiveTrace, | ||
fetchTrace, | ||
...((bindActionCreators(timelineActions, dispatch) as unknown) as TDispatchPropsTimelineViewer), |
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.
Not sure if the preferred way to do this. Seen it at few places and is definitely shorter than destructuring all the functions and then assign them again, but there is more stuff passed to the component than necessary needed.
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 admittedly have a bias towards verbosity, but I find it clearer and preferable to destructure everything that is necessary and pass it along, rather than (bindActionCreators(actions, dispatch) as unknown) as TType
.
It's a little more verbose in this case, but I'd still prefer it over the cast.
Moving the redux up and passing an all the handlers makes for a pretty big props list but also I realised that all of the redux actions are simple UI toggles like expanding span. I wonder if this is so that navigating to search and back to the same trace will preserve the UI state or if that is just unneeded side-effect. Because I think lots of those could be hidden in a local component state making the props list shorter and probably making the components a bit easier to use if do not need to preserve the UI state on navigation. Another question is whether to keep the |
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #517 +/- ##
==========================================
+ Coverage 92.92% 96.57% +3.64%
==========================================
Files 197 254 +57
Lines 4808 7620 +2812
Branches 1160 1986 +826
==========================================
+ Hits 4468 7359 +2891
+ Misses 299 261 -38
+ Partials 41 0 -41 ☔ View full report in Codecov by Sentry. |
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.
Hi @aocenas, thanks again for your patience with this, sorry it took so long to circle back to.
Big picture this looks good, I left some feedback to clean it up a bit and make it a bit DRYer. I don't believe it will take long to address my feedback, but of course let me know if you have any questions or disagree.
@@ -80,13 +80,14 @@ describe('makeShortcutCallbacks()', () => { | |||
}); | |||
|
|||
describe('<TracePage>', () => { | |||
TraceTimelineViewer.prototype.shouldComponentUpdate.mockReturnValue(false); | |||
TraceTimelineViewer.mockReturnValue(''); |
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.
what does this do? I've never mocked the return value of a React component before.
describe('focusSpan', () => { | ||
it('calls updateUiFind and focusUiFindMatches', () => { | ||
const spanName = 'span1'; | ||
wrapper.instance().focusSpan(spanName); |
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 believe to follow the pattern (generally) present in the code base, this should be: wrapper.find(TraceTimelineView).prop('focusSpan')(spanName);
reason being: testing wrapper.instance().fnName(arg)
can lean towards testing implementation, while testing someChildComponent.prop('fnName')(arg)
tests functionality (in this case child component is able to set and focus uiFind)
import { TraceArchive } from '../../types/archive'; | ||
import { EmbeddedState } from '../../types/embedded'; | ||
import filterSpans from '../../utils/filter-spans'; | ||
import updateUiFind from '../../utils/update-ui-find'; | ||
|
||
import './index.css'; | ||
import TTraceTimeline from '../../types/TTraceTimeline'; | ||
|
||
type TDispatchPropsTimelineViewer = { |
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.
this type should exist somewhere that VirtualizedTraceView
can import it, to be DRYer.
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.
perhaps TTraceTimelineDispatchFns
in ../../types/TTraceTimeline
|
||
type TDispatchProps = { | ||
// was from redux |
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.
rather than commenting this, a type should be imported and TVirtualizedTraceViewOwnProps
can be called TProps
(no separation of own vs dispatch props) which would look like:
TProps = {
currentViewRangeTime: [number, number];
findMatchesIDs: Set<string> | TNil;
focusSpan: (uiFind: string) => void;
scrollToFirstVisibleSpan: () => void;
registerAccessors: (accesors: Accessors) => void;
trace: Trace;
} & TImportedType;
@@ -332,6 +310,7 @@ export class VirtualizedTraceViewImpl extends React.Component<VirtualizedTraceVi | |||
findMatchesIDs, | |||
spanNameColumnWidth, | |||
trace, | |||
focusSpan, |
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.
admittedly nit, but please destructure and pass focusSpan
in alphabetical order.
@@ -71,17 +90,17 @@ type TOwnProps = { | |||
match: Match<{ id: string }>; | |||
}; | |||
|
|||
type TReduxProps = { | |||
type TReduxProps = TExtractUiFindFromStateReturn & { |
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.
👍
acknowledgeArchive, | ||
archiveTrace, | ||
fetchTrace, | ||
...((bindActionCreators(timelineActions, dispatch) as unknown) as TDispatchPropsTimelineViewer), |
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 admittedly have a bias towards verbosity, but I find it clearer and preferable to destructure everything that is necessary and pass it along, rather than (bindActionCreators(actions, dispatch) as unknown) as TType
.
It's a little more verbose in this case, but I'd still prefer it over the cast.
While the case of going from a trace back to search back to that trace in a single session is probably pretty rare, I believe this implementation also ensures that going from the Trace Gantt Chart to the Trace Graph and back to the Gantt Chart preserves the visible spans / span details / KV tables within span details. For this reason I believe it visibility state should not be lost on unmount. However, if we wanted to simplify the props list and keep this functionality, Using session storage instead of a highly verbose props list is actually probably the best approach as it will lessen the burden to embed this component. |
Using session storage makes this a moot point, but in case a similar pattern comes up later: |
Signed-off-by: Andrej Ocenas [email protected]
Which problem is this PR solving?
Short description of the changes