You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native如何控制仅点击提交时执行搜索,阻止自动触发?

解决React Native搜索表单自动触发问题

问题根源

你使用的useSearchListsQuery是RTK Query的查询Hook,它默认会在传入的查询参数变化时自动发起请求。现在你把输入框的实时状态listNameSearch直接作为查询参数,导致每输入一个字符就触发一次搜索,页面聚焦时的自动请求也是同样的原因。

解决方法

通过RTK Query的skip选项禁用自动请求,仅在点击搜索按钮时手动触发查询:

修正后的完整代码

import React, { useContext, useState, useEffect } from "react";
import { View, Text, TouchableOpacity, FlatList } from "react-native";
import GeneralStyles from "../../styles/general";
import FormStyles from "../../styles/forms";
import { TextInput } from "react-native-gesture-handler";
import SeriesCard from "../../components/bookCard";
import Toast from 'react-native-simple-toast';
import { useSearchListsQuery } from "../../store/listSlice";
import { AuthContext } from "../auth/AuthContext";

export default function IndexBooks({ navigation }) {
  const { user } = useContext(AuthContext);

  // 输入框实时输入状态
  const [listNameSearch, setListNameSearch] = useState('');
  // 存储提交的搜索关键词
  const [searchQuery, setSearchQuery] = useState('');
  const [lists, setLists] = useState([]);

  // 配置RTK Query:skip设为true,禁用自动请求
  const {
    data: data = [],
    isLoading: isLoadingLists,
    refetch: refetchLists,
    isSuccess: isSuccessLists,
    isError: isErrorLists,
    error: errorLists,
  } = useSearchListsQuery(
    { listNameSearch: searchQuery, page: 1 },
    { skip: true } // 核心配置:阻止自动发起请求
  );

  // 监听加载状态,避免重复弹出Toast
  useEffect(() => {
    if (isLoadingLists) {
      Toast.show('Searching...');
      console.log('loading lists');
    }
  }, [isLoadingLists]);

  // 请求成功时更新列表数据
  useEffect(() => {
    if (isSuccessLists) {
      setLists(data.data);
      console.log('success loading lists', data.data);
    }
  }, [isSuccessLists, data]);

  // 请求失败时提示错误
  useEffect(() => {
    if (isErrorLists) {
      console.log('Lists error', errorLists);
      Toast.show(errorLists.toString());
    }
  }, [isErrorLists, errorLists]);

  // 点击搜索按钮触发查询
  const handleSearch = () => {
    if (!listNameSearch.trim()) {
      Toast.show('Please enter a list name');
      return;
    }
    setSearchQuery(listNameSearch);
    refetchLists({ listNameSearch: listNameSearch, page: 1 });
  };

  return (
    <View style={GeneralStyles.screen}>
      {/* 统一渲染搜索表单 */}
      <View style={FormStyles.card}>
        <TextInput
          style={FormStyles.input}
          placeholder="List Name"
          value={listNameSearch}
          onChangeText={setListNameSearch}
        />
        <TouchableOpacity
          style={FormStyles.button}
          onPress={handleSearch}
        >
          <Text style={FormStyles.buttonText}>
            Search for List
          </Text>
        </TouchableOpacity>
      </View>

      {/* 渲染搜索结果列表 */}
      {lists.length > 0 && (
        <FlatList
          data={lists}
          keyExtractor={(item) => item.id.toString()}
          renderItem={({ item }) => (
            <SeriesCard book={item} user={user?.id || 0} /> {/* 修正原赋值错误为安全取值 */}
          )}
        />
      )}

      {/* 无结果提示 */}
      {lists.length === 0 && searchQuery && (
        <View style={{ padding: 20, alignItems: 'center' }}>
          <Text>No lists found</Text>
        </View>
      )}
    </View>
  );
}

关键说明

  • skip: true:强制RTK Query不自动发起请求,完全由手动调用refetchLists控制查询时机。
  • 用useEffect监听状态:避免在组件渲染阶段直接执行Toast这类副作用,防止重复触发。
  • 简化JSX结构:移除重复的表单渲染逻辑,统一展示搜索表单,根据列表状态显示无结果提示。
  • 修正属性错误:将user={user.id = 0}的赋值操作改为user={user?.id || 0}的安全取值。

内容的提问来源于stack exchange,提问作者maganthro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 19:05:03