getProps function

Map getProps(
  1. dynamic instance, {
  2. bool traverseWrappers = false,
})

Returns an unmodifiable Map view of props for a ReactElement or composite ReactComponent instance.

For a native Dart component, this returns its react.Component.props in an unmodifiable Map view. For a JS component, this returns the result of unconvertJsProps in an unmodifiable Map view.

If traverseWrappers is true then it will return an unmodifiable Map view of props of the first non-"Wrapper" instance.

Throws if instance is not a valid ReactElement or composite ReactComponent .

Implementation

Map getProps(dynamic/* ReactElement|ReactComponent */ instance, {bool traverseWrappers = false}) {
  // Use `is! Object` since it type-promotes `dynamic` to `Object`
  // in the `else` case, while `!= null` does not.
  if (instance is! Object) {
    throw ArgumentError.notNull('instance');
  }

  var isCompositeComponent = _isCompositeComponent(instance);

  if (isValidElement(instance) || isCompositeComponent) {
    if (traverseWrappers) {
      ComponentTypeMeta instanceTypeMeta;

      if (isCompositeComponent && isDartComponent(instance)) {
        final type = getProperty(getDartComponent(instance)!.jsThis as Object, 'constructor') as ReactClass?;
        instanceTypeMeta = getComponentTypeMeta(type!);
      } else if (isValidElement(instance)) {
        instanceTypeMeta = getComponentTypeMeta((instance as ReactElement).type as Object);
      } else {
        throw ArgumentError.value(instance, 'instance',
            'must either be a Dart component ReactComponent or ReactElement when traverseWrappers is true.');
      }

      if (instanceTypeMeta.isWrapper) {
        assert(isDartComponent(instance), 'Non-dart components should not be wrappers');

        final children = getProps(instance)['children'] as List?;

        if (children != null && children.isNotEmpty && isValidElement(children.first)) {
          return getProps(children.first as Object, traverseWrappers: true);
        }
      }
    }

    // Local variable for null type promotion.
    final elementPropsCache = _elementPropsCache;
    if (elementPropsCache != null && !isCompositeComponent) {
      var cachedView = elementPropsCache[instance];
      if (cachedView != null) return cachedView;
    }

    Map rawPropsOrCopy;

    final dartComponentVersion = _getDartComponentVersionFromInstance(instance);
    if (dartComponentVersion == ReactDartComponentVersion.component) { // ignore: invalid_use_of_protected_member
      rawPropsOrCopy = _getExtendedProps(instance);
    } else if (dartComponentVersion == ReactDartComponentVersion.component2) { // ignore: invalid_use_of_protected_member
      // TODO Since JS props are frozen don't wrap in UnmodifiableMapView once https://github.com/dart-lang/sdk/issues/15432 is fixed
      rawPropsOrCopy = JsBackedMap.backedBy(isCompositeComponent
          ? (instance as ReactComponent).props
          : (instance as ReactElement).props);
    } else {
      rawPropsOrCopy = unconvertJsProps(instance);
    }

    final unmodifiableProps = UnmodifiableMapView(rawPropsOrCopy);
    if (elementPropsCache != null && !isCompositeComponent) {
      elementPropsCache[instance] = unmodifiableProps;
    }

    return unmodifiableProps;
  }

  throw ArgumentError.value(instance, 'instance', 'must be a valid ReactElement or composite ReactComponent');
}