-
Notifications
You must be signed in to change notification settings - Fork 667
Add hook and HOC for consuming Console extensions #3383
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
Add hook and HOC for consuming Console extensions #3383
Conversation
|
/hold |
59c5898 to
36b820e
Compare
36b820e to
b667ded
Compare
|
/hold cancel |
frontend/.eslintrc
Outdated
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.
FYI, this is needed for code like
-// eslint-disable-next-line no-undef
if (process.env.NODE_ENV !== 'production') {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.
FYI, we're using an outdated version of @types/react-redux
$ yarn why @types/react-redux
=> Found "@types/react-redux@6.0.2"
$ yarn why react-redux
=> Found "react-redux@7.1.0"I've tried to bump it to match react-redux but ran into typing errors, so using @ts-ignore comment for now.
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.
FYI, can't use flagPending() or FlagsObject from public/reducers/features.ts as it causes Jest to fail on cyclic dependency.
b667ded to
221698a
Compare
221698a to
10b2a6b
Compare
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.
you can specify state and return value by
| const desiredFlags: FlagsObject = useSelector( | |
| const desiredFlags = useSelector<RootState, FlagsObject>( |
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.
@rawagner Please see #3383 (comment) - we're currently using an outdated version of @types/react-redux so we're missing types for new react-redux APIs like useSelector and shallowEqual.
I'll add type params to useSelector call as suggested.
However, we still need the explicit desiredFlags: FlagsObject type declaration due to missing types - otherwise, this variable would be inferred as any.
Edit: the reason for not updating @types/react-redux to match react-redux version - once we do that, we'll have some type-related errors in existing files - we can fix that in a follow-up PR.
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.
getFlagsFromState will run on every store update, maybe we could consider using reselect and comparing if store substate - state.FLAGS changed before getFlagsFromState
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.
From react-redux useSelector docs:
The selector will be run whenever the function component renders.
useSelector()will also subscribe to the Redux store, and run your selector whenever an action is dispatched.
With
useSelector(), returning a new object every time will always force a re-render by default. If you want to retrieve multiple values from the store, you can:
- Call
useSelector()multiple times, with each call returning a single field value- Use Reselect or a similar library to create a memoized selector that returns multiple values in one object, but only returns a new object when one of the values has changed.
- Use the
shallowEqualfunction from React-Redux as theequalityFnargument touseSelector()
In our useExtensions hook, we're using the 3rd option listed above:
// Compute flags relevant for gating desired extensions
const desiredFlags: FlagsObject = useSelector<RootState, FlagsObject>(
(state: RootState) => getFlagsFromState(desiredExtensions, state),
shallowEqual,
);The useSelector hook already memoizes the object selected from Redux store, based on the second argument (equalityFn) which is === by default, but we're customizing it to shallowEqual comparator.
This is similar to connectToFlags HOC using { areStatePropsEqual: _.isEqual } with the difference that _.isEqual does deep comparison while shallowEqual only compares the object's own properties.
Since we're selecting a simple object { [key: string]: boolean } it doesn't really matter if we use _.isEqual or shallowEqual for comparison.
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.
@rawagner But I'm also OK with using _.isEqual instead of shallowEqual (better parity with connectToFlags in terms of comparator), up to you.
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 I meant is that we could use reselect to compare state before running getFlagsFromState. The second argument in useSelector compares result after getFlagsFromState
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.
We could compare state.FLAGS with old state.FLAGS as FLAGS are not updated that often
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.
@rawagner Sorry, I misunderstood your comment.
I'll use reselect to memoize on RootState.FLAGS sub-state as suggested.
10b2a6b to
653df38
Compare
|
Added one more commit to handle all |
e52760a to
50ede88
Compare
|
/hold |
|
/test e2e-gcp-console |
|
/hold cancel |
|
/retest Please review the full test history for this PR and help us cut down flakes. |
fc0e324 to
2afeafc
Compare
2afeafc to
9b56d80
Compare
|
/lgtm |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: jtomasek, mareklibra, rawagner, vojtechszocs The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
This PR adds the necessary changes for consuming Console extensions in a reactive way:
useExtensionshook (preferred, due to general preference for function components)withExtensionshigher-order component a.k.a HOC (use only with class components)Change summary
flagsobject toExtensiontypeAlwaysOnExtensiontype asExtensionminusflagsFeatureFlagandModelDefinitionextensions as always-on (anything else is gated)PluginStoreto replaceExtensionRegistryin the future (hook and HOC use this)Example usage of
useExtensionshook:Example usage of
withExtensionsHOC: