-
Notifications
You must be signed in to change notification settings - Fork 41
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
prevent prop drilling in beamlineAction components #1589
base: develop
Are you sure you want to change the base?
Conversation
Seems like |
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.
Fantastic stuff!
The only thing I kinda disagree with is moving plotIdByAction
into the global state. I understand you've done it to be able to move some of the logic to the thunk in order to reduce prop drilling even more. While the implementation is great, I will always recommend keeping the state as local as possible over any other consideration.
Here, the state belongs to a very narrow branch of the React tree, and it doesn't need to be persisted server-side. So I reckon it should really remain a local state in BeamlineActionsContainer
.
I see I was hesitant as well and I'm happy to change this back. Maybe we can take another look at this in a later stage again when |
6609694
to
4002706
Compare
I reverted the movement of
|
let parameters = params; | ||
|
||
const parameters = cmd.arguments.map((arg) => | ||
if (Object.keys(params).length === 0 && cmd.argument_type === 'List') { | ||
parameters = cmd.arguments.map((arg) => | ||
arg.type === 'float' ? Number.parseFloat(arg.value) : arg.value, | ||
); | ||
} |
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 kept this If statement I added in the additional commit, which is not on the develop
branch, it basically prevents a lot of if cases in the child components and enforces a clear usage of this function to ensure that all the filtering steps and local state updates are done in the same place.
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.
Yeah, I get you, it's this condition, right? If I'm not mistaken, this condition was not present in the BeamlineActionDialog
(nor in BeamlineActionForm
and AnnotatedBeamlineActionForm
), which was probably a bug?
It might be simpler to have an early return for the List
case and to duplicate the dispatch:
setPlotIdByAction((prev) => ({ ...prev, [currentActionName]: null }));
if (cmd.argument_type === 'List') { // not sure if checking for `Object.keys(params).length === 0` is needed?
const cmdArgs = cmd.arguments.map((arg) =>
arg.type === 'float' ? Number.parseFloat(arg.value) : arg.value,
);
dispatch(startBeamlineAction(cmdName, cmdArgs, showOutput));
return;
}
dispatch(startBeamlineAction(cmdName, params, showOutput));
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 it's great given the number of props we're left with 👏 — I don't think there's a way to remove this handleStartAction
prop completely anyway (because of setPlotIdByAction
)
There's probably potential to go further, like finding a way to dispatch startBeamlineAction
from the child components while still keeping the setPlotIdByAction
call in BeamlineActionsContainer
(and without duplicating logic, perhaps by having a dedicated Redux action to start "List" commands)... but it's not worth the effort IMO.
Huge improvement as is 💯
let parameters = params; | ||
|
||
const parameters = cmd.arguments.map((arg) => | ||
if (Object.keys(params).length === 0 && cmd.argument_type === 'List') { | ||
parameters = cmd.arguments.map((arg) => | ||
arg.type === 'float' ? Number.parseFloat(arg.value) : arg.value, | ||
); | ||
} |
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.
Yeah, I get you, it's this condition, right? If I'm not mistaken, this condition was not present in the BeamlineActionDialog
(nor in BeamlineActionForm
and AnnotatedBeamlineActionForm
), which was probably a bug?
It might be simpler to have an early return for the List
case and to duplicate the dispatch:
setPlotIdByAction((prev) => ({ ...prev, [currentActionName]: null }));
if (cmd.argument_type === 'List') { // not sure if checking for `Object.keys(params).length === 0` is needed?
const cmdArgs = cmd.arguments.map((arg) =>
arg.type === 'float' ? Number.parseFloat(arg.value) : arg.value,
);
dispatch(startBeamlineAction(cmdName, cmdArgs, showOutput));
return;
}
dispatch(startBeamlineAction(cmdName, params, showOutput));
I see, so the length check I added was to have the possibility to pass your own parameters, which is probably not needed. I think the other issue is more that |
This PR is a continuation of the work initialized in #1585 . It mainly focuses on removing props drilling for
BeamlineActions
components in an addition to a few smaller adjustments.Small adjustments:
BeamlineActionsContainer.css
file. It only consisted of one class, that was not used in the code.useCallback
for functions excepthandleOnPlotDisplay
(here it was needed as otherwise re-renders would enter an endless loop. To fix this a refactoring ofPlot1D.jsx
is needed, but this would leave the scope of this PR)null
on the false branch by&&
operationsDEFAULT_DIALOG_POSITION
constant was added toBeamlineActionsDialog
Prop drilling Reducement:
hideOutput
andnewPlotDisplayed
) previously definedBeamlineActionsContainer
down intoBeamlineActionsDialog
(where they are actually getting called)stopBeamlineActions
andstartBeamlineActions
are now dispatched where needed and not in container functions that is passed through the treeBeamlineActionsContainer
takesactionsList
directly from stateBeamlineActionsContainer
no longer synchronizes on state changes to thecurrentAction
. Instead child component do this where needed, reducing the props exchanged between components to a minimum (0 for most)BeamlineActionsContainer
previously had a function attribute calledstartAction
this function did 3 different things before dispatchingstartBeamlineAction
:- Check if action is in
actionlist
- filter arguments of
List
type actions- update internal
plotIDByAction
state. A dictionary that keeps track of all plotIds for every action (probably needs to be revisited during the above mentioned refactoring ofPlot1D
)This logic has been moved into the
startBeamlineAction
thunk instead of being passed down the component tree. This also meant the addition ofplotIDByAction
into the state, including necessary reducer and action