Home > Software design >  why do i get error of Undefined name even when the variable is defined?
why do i get error of Undefined name even when the variable is defined?

Time:08-01

I am getting an undefined name error even when i defined the var in my dart file, Below is the error image

enter image description here

Below is my code

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../providers/products.dart';

class ProductDetailsScreen extends StatelessWidget {
  // final String title;

  // ProductDetailsScreen(this.title);
  static const routeName = '/product-detail';

  @override
  Widget build(BuildContext context) {
    final productId = ModalRoute.of(context)?.settings.arguments as String?;

    if (productId != null) {
      final loadedProduct = Provider.of<Products>(context)
          .items
          .firstWhere((prod) => prod.id == productId);
    }
    return Scaffold(
      appBar: AppBar(
        title: Text(loadedProduct.title),
      ),
    );
  }
}

plus when i try to move the return code-block to the if method like this

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../providers/products.dart';

class ProductDetailsScreen extends StatelessWidget {
  // final String title;

  // ProductDetailsScreen(this.title);
  static const routeName = '/product-detail';

  @override
  Widget build(BuildContext context) {
    final productId = ModalRoute.of(context)?.settings.arguments as String?;

    if (productId != null) {
      final loadedProduct = Provider.of<Products>(context)
          .items
          .firstWhere((prod) => prod.id == productId);

      return Scaffold(
        appBar: AppBar(
          title: Text(loadedProduct.title),
        ),
      );
    }
  }
}

it then throws an error "the body might complete normally, causing null to be returned, but the return type, "widget" is a potentially non-nullable type.

Please i need help as it looks like my unfamiliarity with null-safety is giving me lot of bugs.

CodePudding user response:

Yes, you have your variable defined, but it is not visible in the place where you want to use it.

In your first snippet:

 if (productId != null) {
      final loadedProduct = Provider.of<Products>(context)
          .items
          .firstWhere((prod) => prod.id == productId);
    }
    return Scaffold(
      appBar: AppBar(
        title: Text(loadedProduct.title),
      ),
    );

You created loadedProduct but it is only accessible within {} brackets of your if statement. It is called Lexical Scoping.

In yours second snippets you can see that you try to use loadedProduct variable in a proper scope - it doesn't return undefined. Though notice that if productId is null and its if block doesn't execute - you tells your widget to build nothing - null, which is not possible. Consider simple else clouse to handle it.

if (productId != null) {
      final loadedProduct = Provider.of<Products>(context)
          .items
          .firstWhere((prod) => prod.id == productId);

      return Scaffold(
        appBar: AppBar(
          title: Text(loadedProduct.title),
        ),
      );
    } else { 
      return Container() 
    }

CodePudding user response:

The Second Snippet will not work because you are not handling the return if the productId is null, so you have to always return something at the build() method.

For the First Snippet, the problem is that the variable called loadedProduct is defined inside the if condition block, which is not accessed outside its scope, to solve the problem you can do the following steps:

  1. Define the variable loadedProduct outside the if condition but not as final, e.g. var loadedProduct;
  2. Inside the if condition set the value of the variable, e.g. loadedProduct = Provider.of<Products>(context) ...
  3. By now, you have solved the problem if the productId is not null, but what if it is null?, then you have to think about the UI at this case, you can simply set a default title if the productId is null to better understand the case, e.g. Text(loadedProduct?.title ?? 'No Product Found')

NOTE:

loadedProduct?.title ?? 'No Product Found'

is equivalent to the following:

loadedProduct != null ? loadedProduct.title : 'No Product Found'

CodePudding user response:

loadedPorduct is not available outside the if(productId!=null).

Place this variable out of it, inside the build context.

late  final loadedProduct ;
  final productId = ModalRoute.of(context)?.settings.arguments as String?;

if (productId != null) {
   loadedProduct = Provider.of<Products>(context)
        .items
        .firstWhere((prod) => prod.id == productId);
  }

And use case will be

Text(loadedProduct?.title?? "default TextOn null case"),
  • Related