Skip to content
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 forwardRef2/memo2 which fixes jsification of Dart props #275

Merged
merged 37 commits into from
Sep 10, 2020

Conversation

greglittlefield-wf
Copy link
Collaborator

@greglittlefield-wf greglittlefield-wf commented Aug 13, 2020

Motivation

Dart forwardRef components and memo-wrapped components were being passed JSified props due to the use of JS component factories, when they expected to be getting non-converted Dart props.

forwardRef-memo-bug

Solution

tl;dr: I added forwardRef2/memo2, added a bunch of tests around refs, and fixed a bunch of issues surfaced by test failures.

  • Add forwardRef2 and memo2, which return Dart component factories so they don't convert props

    • I had to make new versions because fixing the issues required return type changes that would be breaking. We can consume these new versions under the hood in over_react's memo/uiForwardRef without any breakages.

    • Remove prop de-converting logic from forwardRef2
      This was only a partial solution to wrapping JS components, only applying to callbacks

      Also, now that we're using Dart component factories, this logic would prevent Dart event handlers from being converted.

      So, since we'll need a more holistic solution to the problem of wrapping JS components, and it wouldn't be easy to retain this logic without breaking other behavior, it was removed.

  • Update common factory tests:

    • Refactor simple ref tests use ref test case objects for consistency and to DRY up setup
    • Add tests for all Dart factories (including forwardRef2/memo2) that Dart props are passed in without being converted
      These verify that the main issue that motivated this PR (converted JS props being passed to Dart components) is fixed
    • Add tests that verify that all ref types work with forwardRef
    • Add tests that chainRef works with refs that come from forwardRef2 callback args (as well as ReactElement, since it experienced a similar problem)
      • This required some code changes in different places to get these passing
    • Add test cases JS ref objects are populated with the correct values
  • Update event handler tests to not test de-conversion of props via forwardRef

QA Instructions

@greglittlefield-wf greglittlefield-wf changed the title Add forwardRef2 which fixes jsification of Dart props Add forwardRef2/memo2 which fixes jsification of Dart props Aug 13, 2020

static String _getJsFunctionName(Function object) =>
Copy link
Collaborator Author

@greglittlefield-wf greglittlefield-wf Aug 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use whitespace-agnostic diff for this section

@@ -551,24 +551,6 @@ main() {
expect(propTypeCheck, isA<JsBackedMap>());
});
});

group('props are received correctly without interop interfering with the values:', () {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were moved to the common factory tests so they run for all Dart components and Dart component HOCs, not just Dart function components

lib/react.dart Outdated Show resolved Hide resolved
Copy link
Collaborator

@aaronlademann-wf aaronlademann-wf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@greglittlefield-wf this is awesome work!

Found a couple of small things.

Also, do we have a test for the case where a memo2 wraps a forwardRef2? I know we loosened the typing on memo2 to allow for it - but I don't think I saw a test asserting that it works. Would be nice to have to prevent future regressions.

test/factory/common_factory_tests.dart Show resolved Hide resolved
test/factory/common_factory_tests.dart Outdated Show resolved Hide resolved
}
});

group('when refs come from sources where they have been potentially converted:', () {
test('ReactElement.ref', () {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥳

test/factory/dart_function_factory_test.dart Outdated Show resolved Hide resolved
test/forward_ref_test.dart Show resolved Hide resolved
test/factory/dart_function_factory_test.dart Outdated Show resolved Hide resolved
test/react_memo_test.dart Outdated Show resolved Hide resolved
@greglittlefield-wf
Copy link
Collaborator Author

@aaronlademann-wf @smaifullerton-wk All feedback has been addressed! (including adding a test case for wrapping forwardRef2 with memo)

@@ -58,64 +111,62 @@ main() {
reason: 'test setup sanity check');
}

group('memo', () {
Copy link
Collaborator Author

@greglittlefield-wf greglittlefield-wf Sep 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best reviewed with whitespace-agnostic diff; this actually didn't change, but was just moved into a function

Copy link
Collaborator

@aaronlademann-wf aaronlademann-wf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@@ -642,97 +643,97 @@ main() {
});

group('useImperativeHandle -', () {
var mountNode = new DivElement();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best viewed with whitespace-agnostic diff; besides changing to forwardRef2, these were just indented

Comment on lines +36 to +38
if (ref is ReactComponent) return ref.dartComponent ?? ref;

return (ref as ReactComponent).dartComponent ?? ref;
return ref;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes were to fix an error when setting a string ref on a component using useImperativeHandle (because it would try to cast the customized ref to ReactComponent).

This an edge-case, but it was easier to fix the issue than to skip testing that case.

@sydneyjodon-wk
Copy link
Collaborator

QAing now... I think this just needs to be formatted?

- dartfmt --line-length=120 --dry-run --set-exit-if-changed .
- |
if [ "$TRAVIS_DART_VERSION" != "dev" ]; then
dartfmt --line-length=120 --dry-run --set-exit-if-changed .
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes failures we were seeing in the Dart dev builds due to the dartfmt being different

@sydneyjodon-wk
Copy link
Collaborator

sydneyjodon-wk commented Sep 9, 2020

  • Verify unit tests pass (CI passes)
  • Smoke test examples
  • Perform QA instructions in over_react PR

QA+1 for every step except:

  • Verify the function components in WSD that originally surfaced these issues still work (@aaronlademann-wf )

@@ -12,7 +12,10 @@ cache:

before_script:
- dartanalyzer .
- dartfmt --line-length=120 --dry-run --set-exit-if-changed .
- |
if [ "$TRAVIS_DART_VERSION" != "dev" ]; then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oooh... nice

@aaronlademann-wf
Copy link
Collaborator

QA +1

  • Verify the function components in WSD that originally surfaced these issues still work

@aaronlademann-wf aaronlademann-wf merged commit f9ab447 into master Sep 10, 2020
@greglittlefield-wf greglittlefield-wf deleted the forwardRef-fix branch February 16, 2022 21:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants