generateExtendedJsProps static method

InteropProps generateExtendedJsProps(
  1. Map props,
  2. ReactNode? children, {
  3. Map? defaultProps,
})

Returns a JavaScript version of the specified props, preprocessed for consumption by ReactJS and prepared for consumption by the react library internals.

Implementation

static InteropProps generateExtendedJsProps(Map props, ReactNode children, {Map? defaultProps}) {
  if (children == null) {
    children = [];
  } else if (children is! Iterable) {
    children = [children];
  }

  // 1. Merge in defaults (if they were specified)
  // 2. Add specified props and children.
  // 3. Remove "reserved" props that should not be visible to the rendered component.

  // [1]
  final extendedProps = (defaultProps != null ? Map.from(defaultProps) : {})
    // [2]
    ..addAll(props)
    ..['children'] = children
    // [3]
    ..remove('key')
    ..remove('ref');

  final internal = ReactDartComponentInternal(extendedProps);

  final interopProps = InteropProps(internal: internal);

  // Don't pass a key into InteropProps if one isn't defined, so that the value will
  // be `undefined` in the JS, which is ignored by React, whereas `null` isn't.
  if (props.containsKey('key')) {
    interopProps.key = props['key'];
  }

  if (props.containsKey('ref')) {
    final ref = props['ref'];

    // If the ref is a callback, pass ReactJS a function that will call it
    // with the Dart Component instance, not the ReactComponent instance.
    //
    // Use CallbackRef<Null> to check arity, since parameters could be non-dynamic, and thus
    // would fail the `is CallbackRef<dynamic>` check.
    // See https://github.com/dart-lang/sdk/issues/34593 for more information on arity checks.
    // ignore: prefer_void_to_null
    if (ref is Function(Never)) {
      assert(!isRefArgumentDefinitelyNonNullable(ref), nonNullableCallbackRefArgMessage);
      interopProps.ref = allowInterop((dynamic instance) {
        // Call as dynamic to perform dynamic dispatch, since we can't cast to CallbackRef<dynamic>,
        // and since calling with non-null values will fail at runtime due to the CallbackRef<Null> typing.
        if (instance is ReactComponent && instance.dartComponent != null) {
          return (ref as dynamic)(instance.dartComponent);
        }

        return (ref as dynamic)(instance);
      });
    } else if (ref is Ref) {
      interopProps.ref = ref.jsRef;
    } else {
      interopProps.ref = ref;
    }
  }

  return interopProps;
}