---
title: Component System
description: An overview of Jasprs component system.
---

---

**Jaspr** comes with a component system that is very similar to Flutters widgets. This is a core design decision of jaspr, in order to look and feel very familiar to developers coming from Flutter. You might think of it as just replacing the word 'Widget' with 'Component' *(which actually was a small part of jasprs development process 😉)*, while keeping the same structure and behavior.

<Warning>
The following page and other documentation assumes, that you have already a basic understanding of Flutters widget 
system, especially the widget tree and the three base widgets: StatelessWidget, StatefulWidget and InheritedWidget.
</Warning>

When building an app or website with **jaspr** you will mostly use these **three** basic components:

## StatelessComponent

A custom component that does not require any mutable state and looks like this:

```dart
class MyComponent extends StatelessComponent {

  const MyComponent({Key? key}): super(key: key);

  Iterable<Component> build(BuildContext context) sync* {
    yield p([text('Hello World')]);
  }
}
```

Similar to Flutter, this component:

- extends the abstract `StatelessComponent` class,
- has a constructor receiving a `Key` and optionally some custom parameters,
- has a `build()` method receiving a `BuildContext`.

Different to Flutter is that the `build()` method does not return a single `Component`, but rather multiple
`Component`s as an `Iterable<Component>`. This is again because a HTML element can always have multiple child elements.

<Info>
This design decision was made based on the core principles of jaspr, explained [here](/jaspr-vs-flutter-web)
</Info>

The recommended way to write `build()` methods with **jaspr** is to use the [**synchronous generator**](https://dart.dev/guides/language/language-tour#generators) pattern.
It allows us to return multiple child components in a declarative way by `yield`ing each component without needing to deal with `List`s or `Iterable`s directly.

To write a sync generator, simply use the `sync*` keyword in the method definition and `yield` one or multiple components:

```dart
  class MyComponent extends StatelessComponent {

    @override
    Iterable<Component> build(BuildContext context) sync* {
      yield ChildA();
      yield ChildB();

      // use if to render a component conditionally
      if (myCondition) {
        yield ChildC();
      }
      
      // use for to render a list of components
      for (var i = 0; i < 10; i++) {
        yield SomeItem(index: i);
      }
    } 
  }
```

If you don't like to use the `sync*` / `yield` syntax, you can always just return a normal `List` from the build method,
like this:

```dart
@override
Iterable<Component> build(BuildContext context) {
  return [
    ChildA(),
    ChildB(),
  ];
}
```

In every other aspect, this component behaves the same as Flutters `StatelessWidget`.

## StatefulComponent

A custom component that has mutable state and looks like this:

```dart
class MyComponent extends StatefulComponent {

  const MyComponent({Key? key}): super(key: key);

  State createState() => MyComponentState();
}

class MyComponentState extends State<MyComponent> {

  Iterable<Component> build(BuildContext context) sync* {
    yield p([text('Hello World')]);
  }
}
```

Similar to Flutter, this component:

- extends the abstract `StatefulComponent` class,
- has a constructor receiving a `Key` and optionally some custom parameters,
- has a `createState()` method returning an instance of its custom state class

and has an associated state class that:

- extends the abstract `State<T>` class,
- has a `build()` method inside the state class receiving a `BuildContext`,
- can have optional `initState()`, `didChangeDependencies()`, and other lifecycle methods.

Different to Flutter, this component:

- can return multiple components inside the `build()` method, just like the [`StatelessComponent`](#statelesscomponent)

In every other aspect, this component behaves the same as Flutters `StatefulWidget`.

## InheritedComponent

A base class for components that efficiently propagate information down the tree and looks like this:

```dart
class MyInheritedComponent extends InheritedComponent {

  const MyInheritedComponent({required Component child, Key? key}) 
    : super(child: child, key: key);

  static MyInheritedComponent of(BuildContext context) {
    final MyInheritedComponent? result = context.dependOnInheritedComponentOfExactType<MyInheritedComponent>();
    assert(result != null, 'No MyInheritedComponent found in context');
    return result!;
  }

  @override
  bool updateShouldNotify(covariant MyInheritedComponent oldComponent) {
    return false;
  }
}
```

In every aspect, this component behaves the same as Flutters `InheritedWidget`.
