@TreeProp are props which are automatically and silently passed from a parent component to its children.

TreeProps are a convenient way to share contextual data or utilities in a tree without having to explicitly pass @Prop to every component in your hierarchy.

A good candidate, for example, is a prefetcher which fetches network images ahead of render time. The prefetcher is widely used since images are common. The prefetcher implementation might be something we define for any Component that needs to use it without having to pass it as @Prop in the entire tree.

Declaring a TreeProp

Each TreeProp is declared and created from a method annotated with @OnCreateTreeProp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@LayoutSpec
public class ParentComponentSpec {
  @OnCreateTreeProp
  static Prefetcher onCreatePrefetcher(
      ComponentContext c,
      @Prop Prefetcher prefetcher) {
      
    return prefetcher;
  }
  
  @OnCreateLayout
  static ComponentLayout onCreateLayout(
      ComponentContext c,
      @Prop Uri imageUri) {
      
    return ChildComponent.create(c)
        .imageUri(imageUri)
        .buildWithLayout();
  }
}

You can only declare one @TreeProp for any given type. If a child of ParentComponent also defines a @TreeProp of type Prefetcher, it will override the value of that @TreeProp for all its children (but not for itself).

Using a TreeProp

The child component can access the TreeProp value through a param annotated with @TreeProp that has the same type as that which was declared in the parents @OnCreateTreeProp method.

1
2
3
4
5
6
7
8
9
10
11
12
13
@LayoutSpec
class ChildComponentSpec {
  @OnCreateLayout
  static ComponentLayout onCreateLayout(
      ComponentContext context,
      @TreeProp Prefetcher prefetcher,
      @Prop Uri imageUri) {
    if (prefetcher != null) {
      prefetcher.prefetch(imageUri);
    }
    ...
  }
}

Please note:

Once created, TreeProp value will be passed down to all children, but will not be accessible from component that created this TreeProp.

If you want to access a TreeProp from the component that created this TreeProp, you can transorm it into @State value like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@LayoutSpec
public class ParentComponentSpec {

  @OnCreateInitialState
  static void createInitialState(
      ComponentContext context,
      StateValue<ImportantHelper> helper) {

    helper.set(new ImportantHelper());
  }

  @OnCreateTreeProp
  static ImportantHelper onCreateHelper(
      ComponentContext c,
      @State ImportantHelper helper) {

    return helper;
  }

And now ImportantHelper instance is accessible as @State as usual:

1
2
3
4
5
6
7
@OnCreateLayout
static ComponentLayout onCreateLayout(
    ComponentContext c,
    @State ImportantHelper helper) {

	//...
}

Edit on GitHub