1

I'm encountering a null safety error in my Flutter Riverpod code when trying to access the 'state' property. The error message says:

"The property 'state' can't be unconditionally accessed because the receiver can be 'null'. Try making the access conditional (using '?.') or adding a null check to the target ('!')."

The main goal is to update the image using Riverpod as the state management solution, ensuring it works seamlessly on both web browsers and mobile devices.

I have the following code snippet that demonstrates the issue:

import 'dart:io';
import 'dart:typed_data';
import 'package:provider/provider.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';


final pickedImageProvider = StateProvider<File?>((ref) => null);
final webImageProvider = StateProvider<Uint8List>((ref) => Uint8List(8));
final tapOffsetProvider = StateProvider<Offset?>((ref) => null);

class ProfileAppBar extends ConsumerWidget {
  const ProfileAppBar({Key? key}) : super(key: key);

  Future<void> _pickImage(BuildContext context) async {
    if (!kIsWeb) {
      final ImagePicker picker = ImagePicker();
      XFile? image = await picker.pickImage(source: ImageSource.gallery);
      if (image != null) {
        var selected = File(image.path);
        context.read(pickedImageProvider).state = selected;
      } else {
        print('No image has been picked ');
      }
    } else if (kIsWeb) {
      final ImagePicker picker = ImagePicker();
      XFile? image = await picker.pickImage(source: ImageSource.gallery);
      if (image != null) {
        var f = await image.readAsBytes();
        context.read(webImageProvider).state = f;
        context.read(pickedImageProvider).state = File('a');
      } else {
        print('No image has been picked ');
      }
    } else {
      print('Something went wrong');
    }
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          ...   Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  Tooltip(
                    message: 'Settings',
                    child: Semantics(
                      label: 'Pomodoro timer settings',
                      enabled: true,
                      readOnly: true,
                      child: IconButton(
                        icon: const Icon(
                          Icons.settings_outlined,
                          color: Color(0xff3B3B3B),
                          size: 24,
                          semanticLabel: 'Pomodoro timer Settings',
                        ),
                        onPressed: () {
                          Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => const Scaffold(),
                            ),
                          );
                        },
                      ),
                    ),
                  ),
                  GestureDetector(
                    behavior: HitTestBehavior.translucent,
                    onTapDown: (details) {
                      ref.read(tapOffsetProvider).state =
                          details.globalPosition;
                    },
                    child: IconButton(
                      onPressed: () {
                        final tapOffset = ref.watch(tapOffsetProvider).state;
                        if (tapOffset != null) {
                          showMenu(
                            position: RelativeRect.fromLTRB(
                              tapOffset!.dx - 150,
                              64,
                              tapOffset.dx ?? 0,
                              0,
                            ),
                            constraints: const BoxConstraints(
                              maxWidth: 600,
                            ),...
        ),
      ),
    );
  }
}

The error occurs specifically in the _pickImage method when I try to set the state of context.read().state. How should I adjust my code to make the access to the 'state' property conditional or how should I properly add a null check to avoid this error?

caroch
  • 105
  • 5

1 Answers1

1

Your code should work fine! I see only one problem with the button:

IconButton(
onPressed: () {
  final tapOffset = ref.read(tapOffsetProvider); // `state` don't required
  if (tapOffset != null) {...}

In callbacks it is necessary to use ref.read.


To use your providers, just add ! if you are sure the value is not null or use ?.

final pickedImageProvider = StateProvider<File?>((ref) => null);

{
  File? pickedImage = ref.read(pickedImageProvider);
  File pickedImageNotNull = ref.read(pickedImageProvider)!;

  String? pickedImagePath = ref.read(pickedImageProvider)?.path;
  String pickedImagePathNotNull = ref.read(pickedImageProvider)!.path;
}

But really your problem is that you forgot to use the .notifier and are not correctly trying to access the state:

context.read(pickedImageProvider.notifier).state = selected;
context.read(webImageProvider.notifier).state = f;
context.read(pickedImageProvider.notifier).state = File('a');

// Or do it this way:
context.read(pickedImageProvider.notifier).update((_) => selected);
context.read(webImageProvider.notifier).update((_) => f);
context.read(pickedImageProvider.notifier).update((_) => File('a'));
Ruble
  • 2,589
  • 3
  • 6
  • 29
  • Thank you for your response. I appreciate your answer. Could you please guide me on where to add the following code snippet? `{ File? pickedImage = ref.read(pickedImageProvider); File pickedImageNotNull = ref.read(pickedImageProvider)!; String? pickedImagePath = ref.read(pickedImageProvider)?.path; String pickedImagePathNotNull = ref.read(pickedImageProvider)!.path; }` this is the error message: "Expected a method, getter, setter or operator declaration. This appears to be incomplete code. Try removing it or completing it." – caroch Jun 16 '23 at 17:35
  • In all places where you use `context.read` or `context.watch` and `ref.watch` or `ref.read` – Ruble Jun 16 '23 at 17:57