Solid API docs

Provides providers to descendants.

Has some special convenience methods for Signals.

Default Constructor

Solid({
  Widget? child,
  Widget Function(BuildContext)? builder,
  List<SolidElement> providers = const [],
});

child is the child that will get access to the providers in its build method. builder is the builder function used to build the child and immediately get access to a BuildContext with the access to the providers. providers is a list of providers that will be accessible to all descendants.

class NameProvider {
  const NameProvider(this.name);
  final String name;

  void dispose() {
    // put your dispose logic here
    // ignore: avoid_print
    print('dispose name provider');
  }
}

class NumberProvider {
  const NumberProvider(this.number);
  final int number;
}

class ProvidersPage extends StatelessWidget {
  const ProvidersPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Providers'),
      ),
      body: Solid(
        providers: [
          Provider<NameProvider>(
            create: () => const NameProvider('Ale'),
            // the dispose method is fired when the [Solid] widget above is removed from the widget tree.
            dispose: (provider) => provider.dispose(),
          ),
          Provider<NumberProvider>(
            create: () => const NumberProvider(1),
            // Do not create the provider lazily, but immediately
            lazy: false,
            id: #firstNumber,
          ),
          Provider<NumberProvider>(
            create: () => const NumberProvider(100),
            // Do not create the provider lazily, but immediately
            lazy: false,
            id: #secondNumber,
          ),
        ],
        child: const SomeChild(),
      ),
    );
  }
}

class SomeChild extends StatelessWidget {
  const SomeChild({super.key});

  @override
  Widget build(BuildContext context) {
    final nameProvider = context.get<NameProvider>();
    final numberProvider = context.get<NumberProvider>(#firstNumber);
    final numberProvider2 = context.get<NumberProvider>(#secondNumber);

    return Center(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Text('name: ${nameProvider.name}'),
          const SizedBox(height: 8),
          Text('number1: ${numberProvider.number}'),
          const SizedBox(height: 8),
          Text('number2: ${numberProvider2.number}'),
        ],
      ),
    );
  }
}

Solid.value constructor

Solid.value({
  SolidElement? element,
  List<SolidElement>? elements,
  required Widget child,
})

Provide a single or multiple SolidElements to a new route.

This is useful for passing multiple providers to modals, because they are spawned in a new tree.

Future<void> openDialog(BuildContext context) {
  return showDialog(
    context: context,
    builder: (_) => Solid.value(
      elements: [
        context.getElement<NameProvider>(),
        context.getElement<NumberProvider>(#firstNumber),
        context.getElement<NumberProvider>(#secondNumber),
      ],
      child: Dialog(
        child: Builder(builder: (innerContext) {
          final nameProvider = innerContext.get<NameProvider>();
          final numberProvider1 =
              innerContext.get<NumberProvider>(#firstNumber);
          final numberProvider2 =
              innerContext.get<NumberProvider>(#secondNumber);
          return SizedBox.square(
            dimension: 100,
            child: Center(
              child: Text('''
name: ${nameProvider.name}
number1: ${numberProvider1.number}
number2: ${numberProvider2.number}
'''),
            ),
          );
        }),
      ),
    ),
  );
}

T context.get<T>([Identifier? id])

Gets a provider of type T from the list of providers. If the provider is not found in the first Solid ancestor, it will go up in the tree until it finds it in another Solid ancestor.

id is an optional parameter that specifies the id of the provider. This is useful when you have multiple providers of the same type and you want to distinguish between them.

This methods throws if the provided cannot be found.

T? context.maybeGet<T>([Identifier? id])

Like context.get, but returns null instead of throwing if the provider cannot be found.

SolidElement<T> getElement<T>([Identifier? id])

Gets a provider of type T from the list of providers. It returns the SolidElement of the provider instead of the provider itself. Can be used in modals to provide access to the provider.

T context.observe<T extends SignalBase<dynamic>>([Identifier? id])

Subscribes to the Signal with the value type of T and the id provided (if any).

class ObserveSignalPage extends StatelessWidget {
  const ObserveSignalPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Solid(
        providers: [
          // provide the count signal to descendants
          Provider<Signal<int>>(create: () => Signal(0)),
        ],
        child: const SomeChild(),
      ),
    );
  }
}

class SomeChild extends StatelessWidget {
  const SomeChild({super.key});

  @override
  Widget build(BuildContext context) {
    // retrieve the count signal
    final count = context.observe<Signal<int>>().value;

    return Center(
      child: Text('count: $count'),
    );
  }
}

void context.update<T>(T Function(T value) callback, [Identifier? id])

Updates the value of the Signal with the value type of T and the id provided (if any).

context.update<int>((value) => value += 1);