通过 RIverpod 的 useTextEditingController 搜索不工作

Searching via useTextEditingController of RIverpod not working

我有一个带有通过 useTextEditingController 提供的控制器的文本字段。控制器文本应该是传递给提供者控制器中的函数的值,以搜索相应的产品并显示它们。但是,没有返回任何搜索结果。我已经通过 print() 语句确认读取并假定传递的值是用户输入到文本字段中的值。对于为什么结果(proList)没有返回到回调以供显示,我束手无策。这是相关的代码片段。

请注意,我通过在查询前将搜索文本转换为小写字母来处理区分大小写问题,以确保这不会影响查询。感谢您的帮助或指点。

search_screen.dart

class SearchScreen extends HookConsumerWidget {
  static const routeName = '/searchScreen';
  SearchScreen({Key? key}) : super(key: key);

  late List<Product> _searchList = [];
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    List<Product> prodSearchList =
        ref.watch(productControllerProvider.notifier).products;

    final _searchTextController = useTextEditingController();
    final FocusNode _node = FocusNode();
    final _isSearchFieldEmpty = useState<bool>(true);
    bool isSearchFieldEmpty() {
      return _searchTextController.text.isEmpty;
    }

    useEffect(() {
      _searchTextController.addListener(() {
        _isSearchFieldEmpty.value = isSearchFieldEmpty();
      });
    }, [_searchTextController]);

    return Scaffold(
      bottomSheet: TextField(
        autofocus: true,
        controller: _searchTextController,
        focusNode: _node,
        decoration: kTextInputDecoration.copyWith(
          hintText: 'Item name here ...',
          filled: true,
          fillColor: Theme.of(context).cardColor,
          prefixIcon: const Icon(Icons.search),
          suffixIcon: IconButton(
            onPressed: _searchTextController.text.isEmpty
                ? null
                : () {
                    _searchTextController.clear();
                  },
            icon: Icon(Icons.close,
                color: _searchTextController.text.isNotEmpty
                    ? Colors.red
                    : Colors.grey),
          ),
        ),
        onChanged: (val) {
          _searchList =
              ref.watch(productControllerProvider.notifier).getBySearch(val);
        },
      ),
      body: _searchTextController.text.isNotEmpty && _searchList.isEmpty
          ? Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: const [
                  SizedBox(
                    height: 50,
                  ),
                  Icon(
                    Icons.search,
                    size: 50,
                  ),
                  SizedBox(
                    height: 60,
                  ),
                  Text(
                    'Sorry no results found.',
                    style: TextStyle(fontSize: 20),
                  ),
                ],
              ),
            )
          : Padding(
              padding: const EdgeInsets.all(8.0),
              child: GridView.builder(
                gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 2,
                  crossAxisSpacing: 10,
                  childAspectRatio: 2 / 3,
                  mainAxisSpacing: 10,
                ),
                itemCount: prodSearchList.length,
                itemBuilder: (context, i) {
                  if (_searchTextController.text.isNotEmpty) {
                    return FeedsProduct(
                      id: _searchList[i].id,
                      description: _searchList[i].description,
                      imageUrl: _searchList[i].imageUrl,
                      isFavorite: _searchList[i].isFavorite,
                      price: _searchList[i].price,
                      quantity: _searchList[i].quantity,
                    );
                  } else {
                    return FeedsProduct(
                      id: prodSearchList[i].id,
                      description: prodSearchList[i].description,
                      imageUrl: prodSearchList[i].imageUrl,
                      isFavorite: prodSearchList[i].isFavorite,
                      price: prodSearchList[i].price,
                      quantity: prodSearchList[i].quantity,
                    );
                  }
                },
              ),
            ),
    );
  }
}

product_controller.dart:

final productControllerProvider = ChangeNotifierProvider<ProductListController>(
  (ref) => ProductListController(),
);

class ProductListController extends ChangeNotifier {
  // ProductListController([List<Product>? state]) : super();

  List<Product> get products => _products;

  List<Product> getByCatName(String catName) {
    List<Product> catList = _products
        .where(
            (e) => e.productCategoryName.toLowerCase() == catName.toLowerCase())
        .toList();
    return catList;
  }

  List<Product> getByBrandName(String brandName) {
    List<Product> brandList = _products
        .where((e) => e.brand.toLowerCase() == brandName.toLowerCase())
        .toList();
    return brandList;
  }

  List<Product> get popularProducts {
    return _products.where((e) => e.isPopular).toList();
  }

  Product getById(String prodId) {
    return _products.firstWhere((e) => e.id == prodId);
  }

  List<Product> getBySearch(String query) {
    List<Product> prodSearchResult = _products
        .where(
          (e) => e.title.toLowerCase() == query.toLowerCase(),
        )
        .toList();
notifyListeners();
    return prodSearchResult;
  }

尝试将 _searchList 创建为 HookState,而不是在您的 class 后期创建。

 final _searchList = useState<List<Product>>([]);
 
 onChanged: (val) {
   _searchList.value = ref.watch(productControllerProvider.notifier).getBySearch(val);
 },

而且你的搜索方法有误,你实际上没有 Apple 产品,你有 Apple MacBookAir ... 所以你的等于 e.title.toLowerCase() == query.toLowerCase() 永远不会是真的,如果你真的想搜索忽略大小写并包含您需要使用 RegExp

的单词
List<Product> getBySearch(String query) {
  final RegExp regex = RegExp(query, caseSensitive: false);
  List<Product> prodSearchResult = _products
    .where((e) => e.title.contains(regex))
    .toList();
  notifyListeners();
  return prodSearchResult;
}