React wrapper: Change the way editor might be passed to HotColumn and HotTable to use render props approach #10793
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Context
Specifying editors as children components marked with "magic"
hot-editor
attribute does not feel idiomatic. It doesn't represent something that is a part of the column, it's purely the column's property. Moreover, this kind of composition allows putting multiple Editors in one column, which is illogical.Another issue is that a custom component needs to inherit from a specific base class, thus needs to be a class-based component, which isn't seen correct in modern React and might be hard to follow for some developers.
Instead, we're proposing to use a variant of render props pattern and allow specifying functional component-based editors via
HotTable
orHotColumn
props directly.Implementation notes
Well, good luck to anyone reviewing this beast.
It took me quite a lot of time to get it to the working state and I'm not extremely satisfied with the shape it takes now, to the extent that I have some doubts if it's better than the previous approach.
There are three layers of the solution:
HotTable
component and itseditor
prop, custom editor component and the dynamic class that bridges them in order to satisfy native Handsontable API. In the previous approach the editor component was required to be class-based, inheriting from a provided base class. In the new approach it needed to be functional, so bridging it to the native Handsontable API via dynamic class is more challenging.In the discussion in #3 we figured out that
useImperativeHandle
might be a good fit to provide HOT editor hook functions from the inner custom editor component to the outer code (eventually to the bridging class), although during the implementation I discovered a bit more constraints/consequences of this approach:this
, there's no way to emulatesuper
pointer easily in non-class-based coderef
access was needed; it means there are two-way refs: custom editor sends its hook functions up via context anduseImperativeHandle
while it receives back the HOT-native editor instance back via another ref.useHotEditor
that wraps the above - it hidesuseImperativeHandle
, providessuper
emulation and returns editor instance refThese together make the final user-facing API like this:
or, if it needs to be customized:
How has this been tested?
Types of changes
Related issue(s):
Affected project(s):
handsontable
@handsontable/angular
@handsontable/react
@handsontable/vue
@handsontable/vue3
Checklist: