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

Make adjustments necessary to support strong-mode compliance for over_react #106

Merged

Conversation

aaronlademann-wf
Copy link
Collaborator

@aaronlademann-wf aaronlademann-wf commented Oct 28, 2016

In order for over_react to become strong mode compliant, a few changes are necessary in the wrapper:

  1. In react.Component:
    1. Remove public props and state fields in-favor of private fields with public getters and setters.
      1. This is so that over_react can add strong typing to props and state within UiComponent / UiStatefulComponent, respectively without generating Dart analyzer errors.
    2. Type the props / state arguments of lifecycle methods as Map

I also cleaned up a few analyzer errors showing in this repo as well.


FYA @greglittlefield-wf @jacehensley-wf @clairesarsam-wf @trentgrover-wf

@@ -5,14 +5,28 @@
/// A Dart library for building UI using ReactJS.
library react;

import 'dart:html' show Element;
Copy link
Collaborator

Choose a reason for hiding this comment

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

lib/react.dart is also used for server-side rendering, and should not import dart:html

/// ReactJS `Component` props.
Map props;
Map get props => _props;
set props(Map value) => _props = value;
Copy link
Collaborator

Choose a reason for hiding this comment

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

As opposed to making these getters/setters, can we just use the @virtual annotation instead? (See meta package 1.0.4 changelog)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@greglittlefield-wf I just tried that, and I still get the following errors in over_react:

ERROR: Field declaration Component.ref cannot be overridden in UiComponent. ([over_react] lib/src/component_declaration/component_base.dart:106)
ERROR: Field declaration Component.props cannot be overridden in UiComponent. ([over_react] lib/src/component_declaration/component_base.dart:179)
ERROR: Field declaration Component.state cannot be overridden in UiStatefulComponent. ([over_react] lib/src/component_declaration/component_base.dart:230)

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe you will need to be using Dart 1.19.1.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually just tried this, still does not work. I found this issue dart-lang/sdk#27452, which makes it seem like strong mode does not allow you to override fields, even with the @virtual annotation. I think that may just be for overriding fields with other fields.

Copy link
Collaborator

Choose a reason for hiding this comment

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

That's too bad. Can we add a code comment, then, explaining that this is for strong mode compliance and adding a TODO linked to that SDK issue?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@greglittlefield-wf good idea.

@@ -13,7 +13,8 @@ int _nextFactoryId = 0;
///
/// This prevents React JS from not printing key warnings it deems as "duplicates".
void renderWithUniqueOwnerName(ReactElement render()) {
ReactDartComponentFactoryProxy factory = react.registerComponent(() => new _OwnerHelperComponent());
ReactDartComponentFactoryProxy factory =
Copy link
Collaborator

Choose a reason for hiding this comment

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

#nit I think in strong mode the LHS typing is unnecessary with this cast. Also, unnecessary parentheses? Could do:

final factory =
    react.registerComponent(() => new _OwnerHelperComponent()) as ReactDartComponentFactoryProxy.

@aaronlademann-wf
Copy link
Collaborator Author

@greglittlefield-wf all feedback addressed except for using the @virtual annotation - which for some reason, doesn't seem to work.

dynamic ref;
/// Returns the component of the specified [ref].
///
/// Returns a [Component] if it is a Dart component, otherwise returns an "Dom component" (Dart `Element`).
Copy link
Collaborator

Choose a reason for hiding this comment

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

#nit Doc comments for getters should be noun phrases: https://www.dartlang.org/guides/language/effective-dart/documentation#prefer-starting-variable-getter-or-setter-comments-with-noun-phrases

Not sure why the comment is referencing the getter itself—doesn't really make sense.

Also, this is missing the case for JS components.

What about:

/// A function that, when called with a String ref, returns the associated component.
///
/// This function will return either:
///
/// * [Component] for Dart components
/// * `ReactElement` for JS composite components
/// * `Element` DOM components

/// Returns the component of the specified [ref].
///
/// Returns a [Component] if it is a Dart component, otherwise returns an "Dom component" (Dart `Element`).
dynamic get ref => _ref;
Copy link
Collaborator

Choose a reason for hiding this comment

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

While we're in here, can we make the type more specific, as we did in over_react?

typedef dynamic _RefTypedef(String ref);

_RefTypedef _ref;

_RefTypedef get ref => _ref;
set ref(_RefTypedef  value) => _ref = value;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@greglittlefield-wf I wasn't sure if that typedef should live here... had it moved over at one point. Will move it back.

@jacehensley-wf
Copy link
Contributor

+1

@aaronlademann-wf
Copy link
Collaborator Author

@greglittlefield-wf ready for a final pass.

Map get state => _state;
set state(Map value) => _state = value;

Ref get ref => _ref;
Copy link
Collaborator

Choose a reason for hiding this comment

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

These getters should have doc comments, since consumers can't see the doc comments of private fields.

What about this:

/// A private field that backs [ref], which is exposed via getter/setter so
/// it can be overridden in strong mode.
///
/// Necessary since the `@virtual` annotation within the meta package
/// [doesn't work for overriding fields](https://github.com/dart-lang/sdk/issues/27452).
///
/// TODO: Switch back to a plain field once this issue is fixed.
Ref _ref;

...

/// A function that returns a component reference:
///
/// * [Component] if it is a Dart component.
/// * `Element` _(DOM node)_ if it is a React DOM component.
Ref get ref => _ref;
set ref(Ref value) => _ref = value;

+ Leaving only the TODO portion on the private field.
@aaronlademann-wf
Copy link
Collaborator Author

@greglittlefield-wf feedback addressed

@greglittlefield-wf
Copy link
Collaborator

+1, awesome stuff!

@aaronlademann-wf
Copy link
Collaborator Author

@trentgrover-wf this is ready for a merge + tag.

@trentgrover-wf trentgrover-wf merged commit 5167432 into Workiva:master Nov 1, 2016
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.

4 participants