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
相关产品推荐
相关产品推荐

