Managing State in Comet
Tags: dotnet, beginners
Published: 2022-01-09 02:25:03

> Comet is a .NET experiment inspired by Flutter and Swift UI for building cross-platform apps with C#.

[Comet](https://github.com/dotnet/Comet) promotes a variation of the Model-View-Update pattern popularized by [The Elm Architecture](https://guide.elm-lang.org/architecture/), [Elmish](https://elmish.github.io/elmish/), [Fabulous](https://fsprojects.github.io/Fabulous/Fabulous.XamarinForms/) and others. The major parts of MVU are:

* **Model:** the state of the app
* **View:** the state represented to the user
* **Update:** a way to update state via messages

State is (almost always) immutable and the changes flow in a single direction. 

![MVU diagram](https://github.com/dotnet/Comet/raw/dev/art/mvu-pattern.png)

## Defining State

Each `View` has its own state and you can define this in a few ways. The most simple is to use `State<T>` to wrap a field in a class that implements [INotifyPropertyRead](https://github.com/Clancey/Comet/blob/master/src/Comet/BindingObject.cs#L13). 

```csharp
readonly State<int> count = 0;
```

Most views will probably have more complex state and you can represent that in the same way, however in order to get updates on property changes you'll want to extend [`BindingObject`](https://github.com/Clancey/Comet/blob/master/src/Comet/BindingObject.cs) and use the get/set helpers. You can see in the Comet project template:

```csharp
public class CometRide : BindingObject
{
    public int Rides
    {
        get => GetProperty<int>();
        set => SetProperty(value);
    }

    public string CometTrain
    {
        get
        {
            return "☄️".Repeat(Rides);
        }
    }
}
```

Now within the `View` you can declare your state just like that simple `int` in the first example:

```csharp
readonly State<CometRide> comet = new();
```

This is equivalent to some code you may see in the older Comet samples:

```csharp
[State]
readonly CometRide comet = new();
```

## Adding State in your View

All UI in Comet is a `View`, and the `[Body]` annotates the method that returns the view construction. This is where we can now binding our state to the UI. You "can" display the comet rides like this:

```csharp
[Body]
View body()
    => new VStack {
            new Text(comet.Rides.ToString())
    };
```

Each `View` takes a minimal set of constructor arguments, and here we pass in the state object and convert the `int` to a `string`. We can even use C# string interpolation to make this nicer.

```csharp
new Text(()=> $"{comet.Rides} rides taken.")
```

Notice we are **now** using the function lambda ``()=>`` here. This is the optimal way to bind your state to views in Comet. Now it can reevaluate that property anytime the state of "comet" changes and apply just that property. The former method without the lambda requires the entire body of that view to be recreated.

## Modifying State in your View

This is a noticeable place where Comet diverges from other MVU implementations. The message and update ceremony is streamlined. To increment the ride count in this example, let's bring in a `Button` view which takes 2 constructor arguments: text for the title, and an action handler.

```csharp
new Button("Increment", ()=>{
    comet.Rides++;
})
```

> When using `State<T>` without a `BindingObject` you'll use `.Value` to access the value you intend to change. Using the first example: `()=> count.Value++`.

This change in state will trigger the body of the view to be reevaluated. Comet uses a virtual DOM, so this is extremely fast. A dif of the view is made, and the changes are applied.

![counter in iOS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gmaq6kgw12jhzhmig7gk.gif)

## Ride the Comet

There is more to be said about managing state beyond just the view, and other options such as Flux. For now this covers the basics and gets you going. 

To get installed and a few other details, check out my [previous setup blog](https://dev.to/davidortinau/comet-development-on-macos-1o38).

And for a bonus, the author of Comet, James Clancey, joined the .NET MAUI Community Standup livestream last week to talk about Comet and answer questions. Enjoy!

{% youtube XfYkwYEl0-Y %}