From 7f1e7d627b5beb2a8d7ad5c60139c50c0b06b9de Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Fri, 1 Mar 2024 14:26:23 -0700 Subject: [PATCH 01/10] Temp override to react-dart branch w/ new typedef --- pubspec.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pubspec.yaml b/pubspec.yaml index e9334ae88..bb250860d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -49,6 +49,10 @@ dependency_overrides: git: url: https://github.com/Workiva/over_react_test ref: null-safety + react: + git: + url: git@github.com:Workiva/react-dart.git + ref: FED-2298_ReactNode_typedef workiva: core_checks: From 86bfdaf464d533516071bf72d3b3257870f0e436 Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Fri, 1 Mar 2024 14:26:29 -0700 Subject: [PATCH 02/10] Export ReactNode type from react-dart --- lib/over_react.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/over_react.dart b/lib/over_react.dart index 673c1607d..e4f6a35fd 100644 --- a/lib/over_react.dart +++ b/lib/over_react.dart @@ -57,7 +57,8 @@ export 'package:react/react_client.dart' setClientConfiguration, chainRefs, ReactElement, - ReactComponentFactoryProxy; + ReactComponentFactoryProxy, + ReactNode; export 'package:react/react_client/react_interop.dart' show ReactErrorInfo, Ref; export 'package:react/hooks.dart' show StateHook, ReducerHook; From 5e84679b11460360292116301a1302e601000f7c Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Fri, 1 Mar 2024 15:22:23 -0700 Subject: [PATCH 03/10] Use ReactNode typedef where appropriate --- lib/react_dom.dart | 2 +- .../_deprecated/error_boundary_mixins.dart | 4 +- .../error_boundary_mixins.over_react.g.dart | 6 +- lib/src/component/error_boundary.dart | 2 +- .../error_boundary.over_react.g.dart | 6 +- .../component/error_boundary_recoverable.dart | 2 +- lib/src/component/prop_mixins.dart | 8 +-- .../component/prop_mixins.over_react.g.dart | 10 +-- lib/src/component/ref_util.dart | 4 +- lib/src/component/suspense_component.dart | 4 +- .../suspense_component.over_react.g.dart | 6 +- lib/src/component/with_transition.dart | 2 + .../component_declaration/component_base.dart | 4 +- .../function_component.dart | 2 +- .../redux_multi_provider.dart | 2 +- lib/src/util/context.dart | 1 + lib/src/util/react_util.dart | 2 +- lib/src/util/react_wrappers.dart | 10 +-- test/mockito.mocks.dart | 70 ++++++++++++++----- .../function_component_test.dart | 2 +- 20 files changed, 94 insertions(+), 55 deletions(-) diff --git a/lib/react_dom.dart b/lib/react_dom.dart index 7b319546f..b2e85173e 100644 --- a/lib/react_dom.dart +++ b/lib/react_dom.dart @@ -44,7 +44,7 @@ import 'package:react/react_dom.dart' as react_dom show render, unmountComponent /// Use [unmountComponentAtNode] to unmount the instance. /// /// > Proxies [react_dom.render]. -dynamic render(/*ReactNode*/ dynamic element, Element mountNode) { +dynamic render(ReactNode element, Element mountNode) { return react_dom.render(element, mountNode); } diff --git a/lib/src/component/_deprecated/error_boundary_mixins.dart b/lib/src/component/_deprecated/error_boundary_mixins.dart index f245e7be9..966dd1777 100644 --- a/lib/src/component/_deprecated/error_boundary_mixins.dart +++ b/lib/src/component/_deprecated/error_boundary_mixins.dart @@ -102,7 +102,7 @@ abstract class _$ErrorBoundaryPropsMixin implements UiProps { /// component tree that crashed. /// /// > Related: [onComponentIsUnrecoverable], [onComponentDidCatch] - ReactElement Function(/*Error||Exception*/dynamic error, ReactErrorInfo? info)? fallbackUIRenderer; + ReactNode Function(/*Error||Exception*/dynamic error, ReactErrorInfo? info)? fallbackUIRenderer; /// The amount of time that is "acceptable" between consecutive identical errors thrown from a component /// within the tree wrapped by this [ErrorBoundary]. @@ -361,7 +361,7 @@ mixin ErrorBoundaryMixin @override - ReactElement Function(dynamic error, ReactErrorInfo? info)? + ReactNode Function(dynamic error, ReactErrorInfo? info)? get fallbackUIRenderer => (props[_$key__fallbackUIRenderer___$ErrorBoundaryPropsMixin] ?? null) - as ReactElement Function(dynamic error, ReactErrorInfo? info)?; + as ReactNode Function(dynamic error, ReactErrorInfo? info)?; /// A renderer that will be used to render "fallback" UI instead of the child /// component tree that crashed. @@ -148,7 +148,7 @@ abstract class ErrorBoundaryPropsMixin implements _$ErrorBoundaryPropsMixin { /// @override set fallbackUIRenderer( - ReactElement Function(dynamic error, ReactErrorInfo? info)? value) => + ReactNode Function(dynamic error, ReactErrorInfo? info)? value) => props[_$key__fallbackUIRenderer___$ErrorBoundaryPropsMixin] = value; /// The amount of time that is "acceptable" between consecutive identical errors thrown from a component diff --git a/lib/src/component/error_boundary.dart b/lib/src/component/error_boundary.dart index f0763b6f7..054033b76 100644 --- a/lib/src/component/error_boundary.dart +++ b/lib/src/component/error_boundary.dart @@ -73,7 +73,7 @@ mixin ErrorBoundaryProps on UiProps { /// component tree that crashed. /// /// > Related: [onComponentIsUnrecoverable], [onComponentDidCatch] - ReactElement? Function(/*Error||Exception*/dynamic error, ReactErrorInfo? info)? fallbackUIRenderer; + ReactNode Function(/*Error||Exception*/dynamic error, ReactErrorInfo? info)? fallbackUIRenderer; /// The amount of time that is "acceptable" between consecutive identical errors thrown from a component /// within the tree wrapped by this [ErrorBoundary]. diff --git a/lib/src/component/error_boundary.over_react.g.dart b/lib/src/component/error_boundary.over_react.g.dart index eaa0b84b2..239f9820e 100644 --- a/lib/src/component/error_boundary.over_react.g.dart +++ b/lib/src/component/error_boundary.over_react.g.dart @@ -280,13 +280,13 @@ mixin $ErrorBoundaryProps on ErrorBoundaryProps { Function(dynamic error, ReactErrorInfo info)? value) => props[_$key__onComponentIsUnrecoverable__ErrorBoundaryProps] = value; @override - ReactElement? Function(dynamic error, ReactErrorInfo? info)? + ReactNode Function(dynamic error, ReactErrorInfo? info)? get fallbackUIRenderer => (props[_$key__fallbackUIRenderer__ErrorBoundaryProps] ?? null) - as ReactElement? Function(dynamic error, ReactErrorInfo? info)?; + as ReactNode Function(dynamic error, ReactErrorInfo? info)?; @override set fallbackUIRenderer( - ReactElement? Function(dynamic error, ReactErrorInfo? info)? value) => + ReactNode Function(dynamic error, ReactErrorInfo? info)? value) => props[_$key__fallbackUIRenderer__ErrorBoundaryProps] = value; @override Duration? get identicalErrorFrequencyTolerance => diff --git a/lib/src/component/error_boundary_recoverable.dart b/lib/src/component/error_boundary_recoverable.dart index a7ea02c5c..b354b9a5b 100644 --- a/lib/src/component/error_boundary_recoverable.dart +++ b/lib/src/component/error_boundary_recoverable.dart @@ -189,7 +189,7 @@ class RecoverableErrorBoundaryComponent? get children { + List? get children { final value = _raw$ReactProps$children; // Most common case; Dart components should all have List children @@ -68,7 +68,7 @@ abstract class _$ReactPropsMixin { return [value]; } - set children(List? value) => _raw$ReactProps$children = value; + set children(List? value) => _raw$ReactProps$children = value; /// A String that differentiates a component from its siblings. /// diff --git a/lib/src/component/prop_mixins.over_react.g.dart b/lib/src/component/prop_mixins.over_react.g.dart index 11b10b033..cce80be3e 100644 --- a/lib/src/component/prop_mixins.over_react.g.dart +++ b/lib/src/component/prop_mixins.over_react.g.dart @@ -13,7 +13,7 @@ abstract class ReactPropsMixin implements _$ReactPropsMixin { static const PropsMeta meta = _$metaForReactPropsMixin; @override - List? get children { + List? get children { final value = _raw$ReactProps$children; if (value is List) return value; if (value == null) { @@ -23,7 +23,7 @@ abstract class ReactPropsMixin implements _$ReactPropsMixin { } @override - set children(List? value) => _raw$ReactProps$children = value; + set children(List? value) => _raw$ReactProps$children = value; @override String? get key => props['key'] as String?; @override @@ -33,14 +33,14 @@ abstract class ReactPropsMixin implements _$ReactPropsMixin { /// @override @Accessor(key: 'children') - dynamic get _raw$ReactProps$children => + ReactNode get _raw$ReactProps$children => (props[_$key___raw$ReactProps$children___$ReactPropsMixin] ?? null) - as dynamic; + as ReactNode; /// @override @Accessor(key: 'children') - set _raw$ReactProps$children(dynamic value) => + set _raw$ReactProps$children(ReactNode value) => props[_$key___raw$ReactProps$children___$ReactPropsMixin] = value; /// Either a String used to retrieve the element at a later time via [react.Component.ref], diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index c8368ba91..5c4a1f632 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -212,7 +212,7 @@ Ref createRef() => react_interop.createRef(); /// _$Foo2Config, // ignore: undefined_identifier /// ); UiFactory uiForwardRef( - dynamic Function(TProps props, dynamic ref) functionComponent, dynamic _config) { + ReactNode Function(TProps props, dynamic ref) functionComponent, dynamic _config) { ArgumentError.checkNotNull(_config, '_config'); if (_config is! UiFactoryConfig) { @@ -231,7 +231,7 @@ UiFactory uiForwardRef( // this will be an empty string. final displayName = config.displayName ?? getFunctionName(functionComponent); - dynamic _uiFunctionWrapper(JsBackedMap props, dynamic ref) { + ReactNode _uiFunctionWrapper(JsBackedMap props, dynamic ref) { return functionComponent(propsFactory!.jsMap(props), ref); } diff --git a/lib/src/component/suspense_component.dart b/lib/src/component/suspense_component.dart index 08819958a..04b8eed42 100644 --- a/lib/src/component/suspense_component.dart +++ b/lib/src/component/suspense_component.dart @@ -67,11 +67,11 @@ mixin SuspensePropsMixin on UiProps { /// The actual UI you intend to render. If children suspends while rendering, the Suspense boundary will /// switch to rendering fallback. @override - /*ReactNode*/ List? get children; + List? get children; /// An alternate UI to render in place of the actual UI if it has not finished loading. Any valid React node is /// accepted, though in practice, a fallback is a lightweight placeholder view, such as a loading spinner or skeleton. /// Suspense will automatically switch to fallback when children suspends, and back to children when the data is ready. /// If fallback suspends while rendering, it will activate the closest parent Suspense boundary. - /*ReactNode*/ dynamic fallback; + ReactNode fallback; } diff --git a/lib/src/component/suspense_component.over_react.g.dart b/lib/src/component/suspense_component.over_react.g.dart index f84f72d45..a870e3998 100644 --- a/lib/src/component/suspense_component.over_react.g.dart +++ b/lib/src/component/suspense_component.over_react.g.dart @@ -14,10 +14,10 @@ part of 'suspense_component.dart'; mixin $SuspensePropsMixin on SuspensePropsMixin { static const PropsMeta meta = _$metaForSuspensePropsMixin; @override - dynamic get fallback => - (props[_$key__fallback__SuspensePropsMixin] ?? null) as dynamic; + ReactNode get fallback => + (props[_$key__fallback__SuspensePropsMixin] ?? null) as ReactNode; @override - set fallback(dynamic value) => + set fallback(ReactNode value) => props[_$key__fallback__SuspensePropsMixin] = value; /* GENERATED CONSTANTS */ static const PropDescriptor _$prop__fallback__SuspensePropsMixin = diff --git a/lib/src/component/with_transition.dart b/lib/src/component/with_transition.dart index d24e43236..ab5cc8269 100644 --- a/lib/src/component/with_transition.dart +++ b/lib/src/component/with_transition.dart @@ -264,6 +264,8 @@ class WithTransitionComponent extends UiStatefulComponent2. // TODO: right now only top level factory declarations will generate props configs. UiFactory uiFunction( - dynamic Function(TProps props) functionComponent, + ReactNode Function(TProps props) functionComponent, dynamic _config, ) { ArgumentError.checkNotNull(_config, '_config'); diff --git a/lib/src/over_react_redux/redux_multi_provider.dart b/lib/src/over_react_redux/redux_multi_provider.dart index f3b7c7e0c..cdd4f3a7a 100644 --- a/lib/src/over_react_redux/redux_multi_provider.dart +++ b/lib/src/over_react_redux/redux_multi_provider.dart @@ -77,7 +77,7 @@ class ReduxMultiProviderComponent @override render() { - dynamic content = props.children; + ReactNode content = props.children; props.storesByContext.forEach((context, store) { content = (ReduxProvider() ..store = store diff --git a/lib/src/util/context.dart b/lib/src/util/context.dart index 4f5e37c34..d3af597c2 100644 --- a/lib/src/util/context.dart +++ b/lib/src/util/context.dart @@ -13,6 +13,7 @@ // limitations under the License. import 'package:meta/meta.dart'; +import 'package:over_react/over_react.dart'; import 'package:over_react/src/component_declaration/builder_helpers.dart'; import 'package:over_react/src/util/prop_key_util.dart'; diff --git a/lib/src/util/react_util.dart b/lib/src/util/react_util.dart index 46d9d2c97..de85cf0ef 100644 --- a/lib/src/util/react_util.dart +++ b/lib/src/util/react_util.dart @@ -105,7 +105,7 @@ abstract class UiPropsMapView extends UiProps { Map get componentDefaultProps => throw UnimplementedError('@PropsMixin instances do not implement defaultProps'); @override - ReactElement build([dynamic children]) => + ReactElement build([ReactNode children]) => throw UnimplementedError('@PropsMixin instances do not implement build'); @override diff --git a/lib/src/util/react_wrappers.dart b/lib/src/util/react_wrappers.dart index 1c7dbad85..705ba23ba 100644 --- a/lib/src/util/react_wrappers.dart +++ b/lib/src/util/react_wrappers.dart @@ -195,7 +195,7 @@ Map getProps(dynamic/* ReactElement|ReactComponent */ instance, {bool traverseWr /// /// This method simply wraps react.findDOMNode with strong typing for the return value /// (and for the function itself, which is declared using `var` in react-dart). -Element? findDomNode(dynamic instance) => react_dom.findDOMNode(instance) as Element?; +Element? findDomNode(ReactNode instance) => react_dom.findDOMNode(instance) as Element?; /// Returns a portal that renders [children] into a [container]. /// @@ -204,7 +204,7 @@ Element? findDomNode(dynamic instance) => react_dom.findDOMNode(instance) as Ele /// [children] can be any renderable React child, such as a [ReactElement], [String], or fragment. /// /// See: -ReactPortal createPortal(dynamic children, Element container) => ReactDom.createPortal(children, container); +ReactPortal createPortal(ReactNode children, Element container) => ReactDom.createPortal(children, container); /// Dart wrapper for React.isValidElement. /// @@ -223,7 +223,7 @@ bool isDomElement(dynamic instance) { /// Returns whether [instance] is a composite [ReactComponent]. /// /// __Not for external use.__ -bool _isCompositeComponent(Object? instance) { +bool _isCompositeComponent(ReactNode instance) { return instance != null && getProperty(instance, 'isReactComponent') != null; } @@ -240,7 +240,7 @@ bool _isCompositeComponent(Object? instance) { /// * Children are likewise copied and potentially overwritten with [newChildren] as expected. /// * For JS components, a JS copy of [newProps] is returned, since React will merge the props without any special handling. /// If these values might contain event handlers -dynamic preparePropsChangeset(ReactElement element, Map? newProps, [Iterable? newChildren]) { +dynamic preparePropsChangeset(ReactElement element, Map? newProps, [ReactNode newChildren]) { final type = element.type; final dartComponentVersion = ReactDartComponentVersion.fromType(type); // ignore: invalid_use_of_protected_member @@ -294,7 +294,7 @@ external ReactElement _cloneElement(element, [props, children]); /// > Unlike React.addons.cloneWithProps, key and ref from the original element will be preserved. /// > There is no special behavior for merging any props (unlike cloneWithProps). /// > See the [v0.13 RC2 blog post](https://facebook.github.io/react/blog/2015/03/03/react-v0.13-rc2.html) for additional details. -ReactElement cloneElement(ReactElement element, [Map? props, Iterable? children]) { +ReactElement cloneElement(ReactElement element, [Map? props, ReactNode children]) { ArgumentError.checkNotNull(element, 'element'); var propsChangeset = preparePropsChangeset(element, props, children); diff --git a/test/mockito.mocks.dart b/test/mockito.mocks.dart index abff00e9d..d839bdb20 100644 --- a/test/mockito.mocks.dart +++ b/test/mockito.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.0 from annotations +// Mocks generated by Mockito 5.4.2 from annotations // in over_react/test/mockito.dart. // Do not manually edit this file. @@ -42,16 +42,19 @@ class MockLogger extends _i1.Mock implements _i3.Logger { Invocation.getter(#name), returnValue: '', ) as String); + @override Map get children => (super.noSuchMethod( Invocation.getter(#children), returnValue: {}, ) as Map); + @override String get fullName => (super.noSuchMethod( Invocation.getter(#fullName), returnValue: '', ) as String); + @override _i2.Level get level => (super.noSuchMethod( Invocation.getter(#level), @@ -60,6 +63,7 @@ class MockLogger extends _i1.Mock implements _i3.Logger { Invocation.getter(#level), ), ) as _i2.Level); + @override set level(_i2.Level? value) => super.noSuchMethod( Invocation.setter( @@ -68,11 +72,19 @@ class MockLogger extends _i1.Mock implements _i3.Logger { ), returnValueForMissingStub: null, ); + + @override + _i4.Stream<_i2.Level?> get onLevelChanged => (super.noSuchMethod( + Invocation.getter(#onLevelChanged), + returnValue: _i4.Stream<_i2.Level?>.empty(), + ) as _i4.Stream<_i2.Level?>); + @override _i4.Stream<_i5.LogRecord> get onRecord => (super.noSuchMethod( Invocation.getter(#onRecord), returnValue: _i4.Stream<_i5.LogRecord>.empty(), ) as _i4.Stream<_i5.LogRecord>); + @override void clearListeners() => super.noSuchMethod( Invocation.method( @@ -81,6 +93,7 @@ class MockLogger extends _i1.Mock implements _i3.Logger { ), returnValueForMissingStub: null, ); + @override bool isLoggable(_i2.Level? value) => (super.noSuchMethod( Invocation.method( @@ -89,6 +102,7 @@ class MockLogger extends _i1.Mock implements _i3.Logger { ), returnValue: false, ) as bool); + @override void log( _i2.Level? logLevel, @@ -110,6 +124,7 @@ class MockLogger extends _i1.Mock implements _i3.Logger { ), returnValueForMissingStub: null, ); + @override void finest( Object? message, [ @@ -127,6 +142,7 @@ class MockLogger extends _i1.Mock implements _i3.Logger { ), returnValueForMissingStub: null, ); + @override void finer( Object? message, [ @@ -144,6 +160,7 @@ class MockLogger extends _i1.Mock implements _i3.Logger { ), returnValueForMissingStub: null, ); + @override void fine( Object? message, [ @@ -161,6 +178,7 @@ class MockLogger extends _i1.Mock implements _i3.Logger { ), returnValueForMissingStub: null, ); + @override void config( Object? message, [ @@ -178,6 +196,7 @@ class MockLogger extends _i1.Mock implements _i3.Logger { ), returnValueForMissingStub: null, ); + @override void info( Object? message, [ @@ -195,6 +214,7 @@ class MockLogger extends _i1.Mock implements _i3.Logger { ), returnValueForMissingStub: null, ); + @override void warning( Object? message, [ @@ -212,6 +232,7 @@ class MockLogger extends _i1.Mock implements _i3.Logger { ), returnValueForMissingStub: null, ); + @override void severe( Object? message, [ @@ -229,6 +250,7 @@ class MockLogger extends _i1.Mock implements _i3.Logger { ), returnValueForMissingStub: null, ); + @override void shout( Object? message, [ @@ -257,31 +279,37 @@ class MockMap extends _i1.Mock implements Map { Invocation.getter(#entries), returnValue: >[], ) as Iterable>); + @override Iterable get keys => (super.noSuchMethod( Invocation.getter(#keys), returnValue: [], ) as Iterable); + @override Iterable get values => (super.noSuchMethod( Invocation.getter(#values), returnValue: [], ) as Iterable); + @override int get length => (super.noSuchMethod( Invocation.getter(#length), returnValue: 0, ) as int); + @override bool get isEmpty => (super.noSuchMethod( Invocation.getter(#isEmpty), returnValue: false, ) as bool); + @override bool get isNotEmpty => (super.noSuchMethod( Invocation.getter(#isNotEmpty), returnValue: false, ) as bool); + @override Map cast() => (super.noSuchMethod( Invocation.method( @@ -290,6 +318,7 @@ class MockMap extends _i1.Mock implements Map { ), returnValue: {}, ) as Map); + @override bool containsValue(Object? value) => (super.noSuchMethod( Invocation.method( @@ -298,6 +327,7 @@ class MockMap extends _i1.Mock implements Map { ), returnValue: false, ) as bool); + @override bool containsKey(Object? key) => (super.noSuchMethod( Invocation.method( @@ -306,6 +336,7 @@ class MockMap extends _i1.Mock implements Map { ), returnValue: false, ) as bool); + @override void operator []=( K? key, @@ -321,13 +352,13 @@ class MockMap extends _i1.Mock implements Map { ), returnValueForMissingStub: null, ); + @override Map map( MapEntry Function( - K, - V, - )? - convert) => + K, + V, + )? convert) => (super.noSuchMethod( Invocation.method( #map, @@ -335,6 +366,7 @@ class MockMap extends _i1.Mock implements Map { ), returnValue: {}, ) as Map); + @override void addEntries(Iterable>? newEntries) => super.noSuchMethod( Invocation.method( @@ -343,6 +375,7 @@ class MockMap extends _i1.Mock implements Map { ), returnValueForMissingStub: null, ); + @override V update( K? key, @@ -364,13 +397,13 @@ class MockMap extends _i1.Mock implements Map { ifAbsent: ifAbsent, ), ) as V); + @override void updateAll( V Function( - K, - V, - )? - update) => + K, + V, + )? update) => super.noSuchMethod( Invocation.method( #updateAll, @@ -378,13 +411,13 @@ class MockMap extends _i1.Mock implements Map { ), returnValueForMissingStub: null, ); + @override void removeWhere( bool Function( - K, - V, - )? - test) => + K, + V, + )? test) => super.noSuchMethod( Invocation.method( #removeWhere, @@ -392,6 +425,7 @@ class MockMap extends _i1.Mock implements Map { ), returnValueForMissingStub: null, ); + @override V putIfAbsent( K? key, @@ -410,6 +444,7 @@ class MockMap extends _i1.Mock implements Map { ifAbsent, ), ) as V); + @override void addAll(Map? other) => super.noSuchMethod( Invocation.method( @@ -418,6 +453,7 @@ class MockMap extends _i1.Mock implements Map { ), returnValueForMissingStub: null, ); + @override void clear() => super.noSuchMethod( Invocation.method( @@ -426,13 +462,13 @@ class MockMap extends _i1.Mock implements Map { ), returnValueForMissingStub: null, ); + @override void forEach( void Function( - K, - V, - )? - action) => + K, + V, + )? action) => super.noSuchMethod( Invocation.method( #forEach, diff --git a/test/over_react/component_declaration/non_null_safe_builder_integration_tests/new_boilerplate/function_component_test.dart b/test/over_react/component_declaration/non_null_safe_builder_integration_tests/new_boilerplate/function_component_test.dart index fb6f4594b..dea52eda9 100644 --- a/test/over_react/component_declaration/non_null_safe_builder_integration_tests/new_boilerplate/function_component_test.dart +++ b/test/over_react/component_declaration/non_null_safe_builder_integration_tests/new_boilerplate/function_component_test.dart @@ -143,7 +143,7 @@ main() { GenericUiProps props; setUp(() { - final genericFactory = uiFunction((_) {}, UiFactoryConfig()); + final genericFactory = uiFunction((_) { return null; }, UiFactoryConfig()); final factoryProps = genericFactory(); expect(factoryProps, isA(), reason: 'test setup check'); props = factoryProps as GenericUiProps; From e752442bccead846e707e50f50ebef8b78d9244e Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Mon, 4 Mar 2024 10:37:10 -0700 Subject: [PATCH 04/10] Use https for dep override --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index bb250860d..b467996b4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -51,7 +51,7 @@ dependency_overrides: ref: null-safety react: git: - url: git@github.com:Workiva/react-dart.git + url: https://github.com/Workiva/react-dart.git ref: FED-2298_ReactNode_typedef workiva: From f0f36663697ba533f9dc6d6fa5ccb292283ff164 Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Mon, 4 Mar 2024 12:09:34 -0700 Subject: [PATCH 05/10] Consume react 7.1.0 --- pubspec.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index b467996b4..7b72da5c1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: meta: ^1.6.0 package_config: ^2.1.0 path: ^1.5.1 - react: ^7.0.0 + react: ^7.1.0 redux: '>=5.0.0 <6.0.0' source_span: ^1.4.1 transformer_utils: ^0.2.6 @@ -49,10 +49,6 @@ dependency_overrides: git: url: https://github.com/Workiva/over_react_test ref: null-safety - react: - git: - url: https://github.com/Workiva/react-dart.git - ref: FED-2298_ReactNode_typedef workiva: core_checks: From daed633cca2aeafac1b1f712fbf34acaeee3a873 Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Mon, 4 Mar 2024 12:09:43 -0700 Subject: [PATCH 06/10] Remove unnecessary import --- lib/src/util/context.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/util/context.dart b/lib/src/util/context.dart index d3af597c2..4f5e37c34 100644 --- a/lib/src/util/context.dart +++ b/lib/src/util/context.dart @@ -13,7 +13,6 @@ // limitations under the License. import 'package:meta/meta.dart'; -import 'package:over_react/over_react.dart'; import 'package:over_react/src/component_declaration/builder_helpers.dart'; import 'package:over_react/src/util/prop_key_util.dart'; From 5b00b97a6e5806085507916ba67343f111705598 Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Mon, 4 Mar 2024 12:13:15 -0700 Subject: [PATCH 07/10] Revert breaking changes --- lib/src/component/ref_util.dart | 4 ++-- lib/src/component_declaration/function_component.dart | 2 +- lib/src/util/react_wrappers.dart | 4 ++-- .../new_boilerplate/function_component_test.dart | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index 5c4a1f632..d5159ed69 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -212,7 +212,7 @@ Ref createRef() => react_interop.createRef(); /// _$Foo2Config, // ignore: undefined_identifier /// ); UiFactory uiForwardRef( - ReactNode Function(TProps props, dynamic ref) functionComponent, dynamic _config) { + /*ReactNode*/ dynamic Function(TProps props, dynamic ref) functionComponent, dynamic _config) { ArgumentError.checkNotNull(_config, '_config'); if (_config is! UiFactoryConfig) { @@ -231,7 +231,7 @@ UiFactory uiForwardRef( // this will be an empty string. final displayName = config.displayName ?? getFunctionName(functionComponent); - ReactNode _uiFunctionWrapper(JsBackedMap props, dynamic ref) { + /*ReactNode*/ dynamic _uiFunctionWrapper(JsBackedMap props, dynamic ref) { return functionComponent(propsFactory!.jsMap(props), ref); } diff --git a/lib/src/component_declaration/function_component.dart b/lib/src/component_declaration/function_component.dart index 1ee0ccb44..ba3d6b16d 100644 --- a/lib/src/component_declaration/function_component.dart +++ b/lib/src/component_declaration/function_component.dart @@ -96,7 +96,7 @@ export 'component_type_checking.dart' /// Learn more: . // TODO: right now only top level factory declarations will generate props configs. UiFactory uiFunction( - ReactNode Function(TProps props) functionComponent, + /*ReactNode*/ dynamic Function(TProps props) functionComponent, dynamic _config, ) { ArgumentError.checkNotNull(_config, '_config'); diff --git a/lib/src/util/react_wrappers.dart b/lib/src/util/react_wrappers.dart index 705ba23ba..1421d682e 100644 --- a/lib/src/util/react_wrappers.dart +++ b/lib/src/util/react_wrappers.dart @@ -240,7 +240,7 @@ bool _isCompositeComponent(ReactNode instance) { /// * Children are likewise copied and potentially overwritten with [newChildren] as expected. /// * For JS components, a JS copy of [newProps] is returned, since React will merge the props without any special handling. /// If these values might contain event handlers -dynamic preparePropsChangeset(ReactElement element, Map? newProps, [ReactNode newChildren]) { +dynamic preparePropsChangeset(ReactElement element, Map? newProps, [Iterable? newChildren]) { final type = element.type; final dartComponentVersion = ReactDartComponentVersion.fromType(type); // ignore: invalid_use_of_protected_member @@ -294,7 +294,7 @@ external ReactElement _cloneElement(element, [props, children]); /// > Unlike React.addons.cloneWithProps, key and ref from the original element will be preserved. /// > There is no special behavior for merging any props (unlike cloneWithProps). /// > See the [v0.13 RC2 blog post](https://facebook.github.io/react/blog/2015/03/03/react-v0.13-rc2.html) for additional details. -ReactElement cloneElement(ReactElement element, [Map? props, ReactNode children]) { +ReactElement cloneElement(ReactElement element, [Map? props, Iterable? children]) { ArgumentError.checkNotNull(element, 'element'); var propsChangeset = preparePropsChangeset(element, props, children); diff --git a/test/over_react/component_declaration/non_null_safe_builder_integration_tests/new_boilerplate/function_component_test.dart b/test/over_react/component_declaration/non_null_safe_builder_integration_tests/new_boilerplate/function_component_test.dart index dea52eda9..fb6f4594b 100644 --- a/test/over_react/component_declaration/non_null_safe_builder_integration_tests/new_boilerplate/function_component_test.dart +++ b/test/over_react/component_declaration/non_null_safe_builder_integration_tests/new_boilerplate/function_component_test.dart @@ -143,7 +143,7 @@ main() { GenericUiProps props; setUp(() { - final genericFactory = uiFunction((_) { return null; }, UiFactoryConfig()); + final genericFactory = uiFunction((_) {}, UiFactoryConfig()); final factoryProps = genericFactory(); expect(factoryProps, isA(), reason: 'test setup check'); props = factoryProps as GenericUiProps; From 374ab79dd5d3ae47bb354177db77086a7e10a69f Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Mon, 4 Mar 2024 14:56:41 -0700 Subject: [PATCH 08/10] Fix test (maybe) --- test/over_react/component_declaration/component_base_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/over_react/component_declaration/component_base_test.dart b/test/over_react/component_declaration/component_base_test.dart index 59d55ad0e..d6e189ac7 100644 --- a/test/over_react/component_declaration/component_base_test.dart +++ b/test/over_react/component_declaration/component_base_test.dart @@ -499,7 +499,7 @@ main() { }); test('null: returns an empty list', () { - expect(getTypedView({childrenKey: null}).children, same(const [])); + expect(getTypedView({childrenKey: null}).children, same(const [])); }); test('a single child: wraps in a list', () { From d9129a31afa762ae8a50fefb3cd33a825ca1ea7f Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Tue, 13 Aug 2024 11:38:17 -0700 Subject: [PATCH 09/10] Revert incorrect types --- lib/src/util/react_wrappers.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/util/react_wrappers.dart b/lib/src/util/react_wrappers.dart index f0f8e2f30..65906641b 100644 --- a/lib/src/util/react_wrappers.dart +++ b/lib/src/util/react_wrappers.dart @@ -194,7 +194,7 @@ Map getProps(dynamic/* ReactElement|ReactComponent */ instance, {bool traverseWr /// /// This method simply wraps react.findDOMNode with strong typing for the return value /// (and for the function itself, which is declared using `var` in react-dart). -Element? findDomNode(ReactNode instance) => react_dom.findDOMNode(instance) as Element?; +Element? findDomNode(dynamic instance) => react_dom.findDOMNode(instance) as Element?; /// Returns a portal that renders [children] into a [container]. /// @@ -222,7 +222,7 @@ bool isDomElement(dynamic instance) { /// Returns whether [instance] is a composite [ReactComponent]. /// /// __Not for external use.__ -bool _isCompositeComponent(ReactNode instance) { +bool _isCompositeComponent(Object? instance) { return instance != null && getProperty(instance, 'isReactComponent') != null; } From c5119fffedb47c86e23fae88d68f121312f955e9 Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Mon, 19 Aug 2024 08:40:02 -0700 Subject: [PATCH 10/10] Revert breaking change --- lib/src/component/prop_mixins.dart | 8 ++++---- lib/src/component/prop_mixins.over_react.g.dart | 10 +++++----- .../component_declaration/component_base_test.dart | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/src/component/prop_mixins.dart b/lib/src/component/prop_mixins.dart index 80522ee0a..a2ff6f191 100644 --- a/lib/src/component/prop_mixins.dart +++ b/lib/src/component/prop_mixins.dart @@ -17,7 +17,7 @@ /// Various prop related mixins to be used with `UiComponent` descendants. library over_react.prop_mixins; -import 'package:over_react/over_react.dart' show AriaPropsMapView, AriaPropsMixin, DomProps, PropsMeta, ReactNode; +import 'package:over_react/over_react.dart' show AriaPropsMapView, AriaPropsMixin, DomProps, PropsMeta; // Must import these consts because they are used in the transformed code. // ignore: deprecated_member_use, unused_shown_name import 'package:over_react/over_react.dart' show PropDescriptor, ConsumedProps, PropsMeta; @@ -46,10 +46,10 @@ abstract class _$ReactPropsMixin { // This private field is namespaced to avoid colliding with other classes. @Accessor(key: 'children') - ReactNode _raw$ReactProps$children; + dynamic _raw$ReactProps$children; /// The children that were passed in to this component when it was built. - List? get children { + List? get children { final value = _raw$ReactProps$children; // Most common case; Dart components should all have List children @@ -68,7 +68,7 @@ abstract class _$ReactPropsMixin { return [value]; } - set children(List? value) => _raw$ReactProps$children = value; + set children(List? value) => _raw$ReactProps$children = value; /// A String that differentiates a component from its siblings. /// diff --git a/lib/src/component/prop_mixins.over_react.g.dart b/lib/src/component/prop_mixins.over_react.g.dart index cce80be3e..11b10b033 100644 --- a/lib/src/component/prop_mixins.over_react.g.dart +++ b/lib/src/component/prop_mixins.over_react.g.dart @@ -13,7 +13,7 @@ abstract class ReactPropsMixin implements _$ReactPropsMixin { static const PropsMeta meta = _$metaForReactPropsMixin; @override - List? get children { + List? get children { final value = _raw$ReactProps$children; if (value is List) return value; if (value == null) { @@ -23,7 +23,7 @@ abstract class ReactPropsMixin implements _$ReactPropsMixin { } @override - set children(List? value) => _raw$ReactProps$children = value; + set children(List? value) => _raw$ReactProps$children = value; @override String? get key => props['key'] as String?; @override @@ -33,14 +33,14 @@ abstract class ReactPropsMixin implements _$ReactPropsMixin { /// @override @Accessor(key: 'children') - ReactNode get _raw$ReactProps$children => + dynamic get _raw$ReactProps$children => (props[_$key___raw$ReactProps$children___$ReactPropsMixin] ?? null) - as ReactNode; + as dynamic; /// @override @Accessor(key: 'children') - set _raw$ReactProps$children(ReactNode value) => + set _raw$ReactProps$children(dynamic value) => props[_$key___raw$ReactProps$children___$ReactPropsMixin] = value; /// Either a String used to retrieve the element at a later time via [react.Component.ref], diff --git a/test/over_react/component_declaration/component_base_test.dart b/test/over_react/component_declaration/component_base_test.dart index ee3bcaaf8..f02b4eef1 100644 --- a/test/over_react/component_declaration/component_base_test.dart +++ b/test/over_react/component_declaration/component_base_test.dart @@ -498,7 +498,7 @@ main() { }); test('null: returns an empty list', () { - expect(getTypedView({childrenKey: null}).children, same(const [])); + expect(getTypedView({childrenKey: null}).children, same(const [])); }); test('a single child: wraps in a list', () {