---
title: "@sync"
description: Easy data synchronization with support for custom data types.
---

---

The `@sync` annotation gives you an easy way to sync state of a `StatefulComponent` from the server to the client.

<Info>
For a general guide about data-fetching on the server see [Data Fetching](/concepts/data_fetching).
</Info>

## Usage

Start by annotating a field of your `StatefulComponent` with `@sync`:

```dart title="lib/my_component.dart"
class MyComponent extends StatefulComponent { /* ... */ }

class MyComponentState extends State<MyComponent> {

  // Use @sync on any field to automatically sync its value from the server to the client.
  @sync
  int myValue = 0;

}
```

Then when running `jaspr serve` or `jaspr build` this will generate a `.sync.dart` alongside your component including
a `<ComponentStateName>SyncMixin` that you have to apply to your state class:

```dart title="lib/my_component.dart"
import 'my_component.sync.dart';

class MyComponent extends StatefulComponent { /* ... */ }

class MyComponentState extends State<MyComponent> with MyComponentStateSyncMixin {

  @sync
  int myValue = 0;

}
```

You can also use the `@sync` annotation on multiple fields of the `State` class.

---

## Custom Data Types

When using `@sync` on a field, that field is

- serialized on the server during pre-rendering as part of the html output
- deserialized on the client during `initState()` when this component is first mounted

Therefore, any annotated field must either have a **primitive serializable type**: `bool`, `int`, `double`, `String` or `List` / `Map`s of these.

Or you can use custom data types by using the `@encoder` and `@decoder` annotations with the class:

```dart title="model.dart"
class Model {
  @decoder
  static Model fromJson(Map<String, dynamic> json) => /* ... */;

  @encoder
  Map<String, dynamic> toJson() => /* ... */;
}
```

Read the docs on the [@encoder / @decoder](/api/utils/at_encoder_decoder) annotations to learn more about how to set up
serialization for custom data types.

With this setup you can use fields of any type with the `@sync` annotation.

## Preloading Data

When using the `@sync` annotation, it is common that you want to preload the data that you then want to sync to the client.

When the data is **synchronous** you can simply assign the value of a `@sync` field in the `initState()` method:

```dart title="lib/my_component.dart"
import 'my_component.sync.dart';

class MyComponent extends StatefulComponent { /* ... */ }

class MyComponentState extends State<MyComponent> with MyComponentStateSyncMixin {

  @sync
  int myValue = 0;

  @override
  void initState() {
    // On the client, [myValue] and any other synced field will be assigned
    // the synced value during the [super.initState()] call.
    super.initState();

    // On the server, we can assign the field during pre-rendering.
    if (!kIsWeb) {
      myValue = getValueOnServer();
    }
  }

  // You can modify any synced value on the client as usual.
  // @sync is only for setting the initial value of a field on the client to a value that has
  // been set during the pre-rendering on the server.
  void increment() {
    setState(() {
      myValue++;
    });
  }
}
```

When the data you want to load is **asynchronous**, you can additionally use the [`PreloadStateMixin`](/api/utils/preload_state_mixin)
to perform any asynchronous work before `initState()` is called on the server:

```dart title="lib/my_component.dart"
import 'my_component.sync.dart';

class MyComponent extends StatefulComponent { /* ... */ }

class MyComponentState extends State<MyComponent> with MyComponentStateSyncMixin, PreloadStateMixin {

  @sync
  int myValue = 0;

  // Perform any async work on the server.
  // This will delay `initState()` and the building of this component until the future is completed.
  Future<void> preloadState() async {
    // Load some async data, e.g. from a database.
    myValue = await getValueFromDatabase();
  }
}
```

Read the docs on [PreloadStateMixin](/api/utils/preload_state_mixin) for more details.

---

## Alternatives

- Check out the [SyncStateMixin](/api/utils/sync_state_mixin) for a more explicit way to sync state of a `StatefulComponent`
  between server and client (this is used by `@sync` under the hood).

- Check out [@client](/api/utils/at_client) components, that support passing data from the server to the client as part
  of the component parameters, including support for custom data types.

