user11874694
user11874694

Reputation:

The argument type 'Products Function(BuildContext, dynamic, dynamic)' can't be assigned to the parameter type 'Products Function(BuildContext)'

I am a new learner following a Flutter tutorial that is written in previous version and I get the following errors with this code:

main.ts:

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider.value(
          value: Auth(),
        ),
        ChangeNotifierProxyProvider<Auth, Products>(
          create: (ctx, auth, previousProducts) => Products(
            auth.token,
            auth.userId,
            previousProducts == null ? [] : previousProducts.items,
          ),
        ),
        ChangeNotifierProvider.value(
          value: Cart(),
        ),
        ChangeNotifierProxyProvider<Auth, Orders>(
          create: (ctx, auth, previousOrders) => Orders(
            auth.token,
            auth.userId,
            previousOrders == null ? [] : previousOrders.orders,
          ),
        ),
      ],
      child: Consumer<Auth>(
        builder: (ctx, auth, _) => MaterialApp(
          title: 'MyShop',
          theme: ThemeData(
            primarySwatch: Colors.purple,
            textSelectionTheme: TextSelectionThemeData(
              selectionColor: Colors.deepOrange,
              selectionHandleColor: Colors.blue,
            ),
            fontFamily: 'Lato',
            pageTransitionsTheme: PageTransitionsTheme(
              builders: {
                TargetPlatform.android: CustomPageTransitionBuilder(),
                TargetPlatform.iOS: CustomPageTransitionBuilder(),
              },
            ),
          ),
          home: auth.isAuth
              ? ProductsOverviewScreen()
              : FutureBuilder(
                  future: auth.tryAutoLogin(),
                  builder: (ctx, authResultSnapshot) =>
                      authResultSnapshot.connectionState ==
                              ConnectionState.waiting
                          ? SplashScreen()
                          : AuthScreen(),
                ),
          routes: {
            ProductDetailScreen.routeName: (ctx) => ProductDetailScreen(),
            CartScreen.routeName: (ctx) => CartScreen(),
            OrdersScreen.routeName: (ctx) => OrdersScreen(),
            UserProductsScreen.routeName: (ctx) => UserProductsScreen(),
            EditProductScreen.routeName: (ctx) => EditProductScreen(),
          },
        ),
      ),
    );
  }
}

The named parameter 'update' is required, but there's no corresponding argument. Try adding the required argument.

The argument type 'Products Function(BuildContext, dynamic, dynamic)' can't be assigned to the parameter type 'Products Function(BuildContext)'.

All the errors come from this part of the code( and the other similar part):

ChangeNotifierProxyProvider<Auth, Products>(
  create: (ctx, auth, previousProducts) => Products(
    auth.token,
    auth.userId,
    previousProducts == null ? [] : previousProducts.items,
  ),

And this is the Products.ts:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

import '../models/http_exception.dart';
import './product.dart';

class Products with ChangeNotifier {
  List<Product> _items = [];
  final String authToken;
  final String userId;

  Products(this.authToken, this.userId, this._items);

  List<Product> get items {
    // if (_showFavoritesOnly) {
    //   return _items.where((prodItem) => prodItem.isFavorite).toList();
    // }
    return [..._items];
  }

  List<Product> get favoriteItems {
    return _items.where((prodItem) => prodItem.isFavorite).toList();
  }

  Product findById(String id) {
    return _items.firstWhere((prod) => prod.id == id);
  }


  Future<void> fetchAndSetProducts([bool filterByUser = false]) async {
    final filterString =
        filterByUser ? 'orderBy="creatorId"&equalTo="$userId"' : '';
    var url = Uri.parse(
        'https://flutter-update.firebaseio.com/products.json?auth=$authToken&$filterString');
    try {
      final response = await http.get(url);
      final extractedData = json.decode(response.body) as Map<String, dynamic>;
      if (extractedData == null) {
        return;
      }
      url = Uri.parse(
          'https://flutter-update.firebaseio.com/userFavorites/$userId.json?auth=$authToken');
      final favoriteResponse = await http.get(url);
      final favoriteData = json.decode(favoriteResponse.body);
      final List<Product> loadedProducts = [];
      extractedData.forEach((prodId, prodData) {
        loadedProducts.add(Product(
          id: prodId,
          title: prodData['title'],
          description: prodData['description'],
          price: prodData['price'],
          isFavorite:
              favoriteData == null ? false : favoriteData[prodId] ?? false,
          imageUrl: prodData['imageUrl'],
        ));
      });
      _items = loadedProducts;
      notifyListeners();
    } catch (error) {
      throw (error);
    }
  }

  Future<void> addProduct(Product product) async {
    final url = Uri.parse(
        'https://flutter-update.firebaseio.com/products.json?auth=$authToken');
    try {
      final response = await http.post(
        url,
        body: json.encode({
          'title': product.title,
          'description': product.description,
          'imageUrl': product.imageUrl,
          'price': product.price,
          'creatorId': userId,
        }),
      );
      final newProduct = Product(
        title: product.title,
        description: product.description,
        price: product.price,
        imageUrl: product.imageUrl,
        id: json.decode(response.body)['name'],
      );
      _items.add(newProduct);
      // _items.insert(0, newProduct); // at the start of the list
      notifyListeners();
    } catch (error) {
      print(error);
      throw error;
    }
  }

  Future<void> updateProduct(String id, Product newProduct) async {
    final prodIndex = _items.indexWhere((prod) => prod.id == id);
    if (prodIndex >= 0) {
      final url = Uri.parse(
          'https://flutter-update.firebaseio.com/products/$id.json?auth=$authToken');
      await http.patch(url,
          body: json.encode({
            'title': newProduct.title,
            'description': newProduct.description,
            'imageUrl': newProduct.imageUrl,
            'price': newProduct.price
          }));
      _items[prodIndex] = newProduct;
      notifyListeners();
    } else {
      print('...');
    }
  }

  Future<void> deleteProduct(String id) async {
    final url = Uri.parse(
        'https://flutter-update.firebaseio.com/products/$id.json?auth=$authToken');
    final existingProductIndex = _items.indexWhere((prod) => prod.id == id);
    Product? existingProduct = _items[existingProductIndex];
    _items.removeAt(existingProductIndex);
    notifyListeners();
    final response = await http.delete(url);
    if (response.statusCode >= 400) {
      _items.insert(existingProductIndex, existingProduct);
      notifyListeners();
      throw HttpException('Could not delete product.');
    }
    existingProduct = null;
  }
}

I don't know what is the problem and how should I solve these errors? I can't find a required parameter named update in the Products class.

Upvotes: 2

Views: 912

Answers (3)

sharib ahmed
sharib ahmed

Reputation: 194

I am assuming you are following Maximillian's udemy course. You are using ChangeNotifierProxy because your Products provider is dependent on Auth provider's variables.

ChangeNotifierProxyProvider<MyModel, MyChangeNotifier>(
create: (_) => MyChangeNotifier(),
update: (_, myModel, myNotifier) => myNotifier
..update(myModel),
child: ...
);

This is how to define a ChangeNotifierProxyProvider. In your case, it will be:

without null safety migration

         ChangeNotifierProxyProvider<Auth, Products>(
         create: null,
         update: (context, auth, previousProducts) => Products(auth.token,
         previousProducts == null ? [] : previousProducts.items, 
         auth.userId)),

with null safety migration

         ChangeNotifierProxyProvider<Auth, Products>(
         create: (ctx) => Products('', '', []),
         update: (context, auth, previousProducts) => 
         Products(auth.token,previousProducts.items,auth.userId)),

Still if you see any error related to update then you need to upgrade your packages.

Let me know if you further need help :)

Upvotes: 4

user11874694
user11874694

Reputation:

Finally I could solve my problem by this modification of code:

providers: [
        ChangeNotifierProvider.value(
          value: Auth(),
        ),
        ChangeNotifierProxyProvider<Auth, Products>(
          create: (ctx) =>
              Products(null as String, null as String, null as List<Product>),
          update: (ctx, auth, previousProducts) => Products(
            auth.token as String,
            auth.userId as String,
            previousProducts == null ? [] : previousProducts.items,
          ),
        ),
        ChangeNotifierProvider.value(
          value: Cart(),
        ),
        ChangeNotifierProxyProvider<Auth, Orders>(
          create: (ctx) =>
              Orders(null as String, null as String, null as  List<OrderItem>),
          update: (ctx, auth, previousOrders) => Orders(
            auth.token as String,
            auth.userId as String,
            previousOrders == null ? [] : previousOrders.orders,
          ),
        ),
      ],

Upvotes: 0

Purushotam Kumar
Purushotam Kumar

Reputation: 1092

Do not use ChangeNotifierProxyProvider to create a new object. This is a provider which depends on other objects as well to update it's value. Use just the Provider by following way:

Provider(
  create: (_) => MyModel(),
  child: ...
)

This should be enough for your use case.

Upvotes: 0

Related Questions