@sync
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.
For a general guide about data-fetching on the server see Data Fetching.
Usage
Start by annotating a field of your StatefulComponent with @sync:
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:
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 / Maps of these.
Or you can use custom data types by using the @encoder and @decoder annotations with the class:
class Model {
  @decoder
  static Model fromJson(Map<String, dynamic> json) => /* ... */;
  @encoder
  Map<String, dynamic> toJson() => /* ... */;
}
Read the docs on the @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:
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
to perform any asynchronous work before initState() is called on the server:
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 for more details.
Alternatives
- 
Check out the SyncStateMixin for a more explicit way to sync state of a
StatefulComponentbetween server and client (this is used by@syncunder the hood). - 
Check out @client components, that support passing data from the server to the client as part of the component parameters, including support for custom data types.
 

