Skip to content

Environment

The @SolidEnvironment() annotation injects a value from the widget tree into your widget. It mirrors SwiftUI’s @Environment property wrapper: type-keyed, lookup happens on first access, and any reactive @SolidState fields on the injected type stay reactive in your build method.

Annotate a late field with @SolidEnvironment() on a StatelessWidget or an existing State<X>:

source/counter_display.dart
class CounterDisplay extends StatelessWidget {
CounterDisplay({super.key});
@SolidEnvironment()
late Counter counter;
@override
Widget build(BuildContext context) {
return Center(child: Text('Counter is ${counter.value}'));
}
}

counter is bound to the nearest ancestor Provider<Counter> in the widget tree on first access. Because Counter.value is a @SolidState field, the read is reactive: only the Text widget rebuilds when counter.value changes — the same fine-grained reactivity you’d get from a same-class @SolidState read.

Given a Counter class that looks like this:

source/counter.dart
class Counter {
@SolidState()
int value = 0;
}

You can provide it with .environment<T>() extension on Widget, shipped by solid_annotations:

source/main.dart
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CounterDisplay().environment((_) => Counter()),
);
}
}

The type argument is inferred from the closure’s return type. Pass it explicitly only when you want consumers to read by a supertype:

HomePage().environment<AuthService>((_) => RealAuthService())

Chained calls nest providers in declaration order:

HomePage()
.environment((_) => Counter())
.environment((_) => Logger())

Or Provider<T> directly from package:provider:

source/main.dart
import 'package:provider/provider.dart';
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Provider(
create: (_) => Counter(),
child: CounterDisplay(),
),
);
}
}

To compose multiple providers, use MultiProvider from package:provider:

MultiProvider(
providers: [
Provider(create: (_) => Counter()),
Provider(create: (_) => Logger()),
],
child: CounterDisplay(),
)