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

React Native搜索页面返回后清空输入与结果的问题求助

解决方案

你的问题出在两个核心点:

  1. 依赖navigation对象的useEffect仅在组件挂载时执行一次,无法在从其他页面返回当前页面时触发清空逻辑
  2. 输入框未与input状态绑定,导致即使重置状态,输入框内容也不会同步更新

具体修改步骤:

1. 导入必要的钩子

添加useFocusEffect和useCallback的导入:

import React, { useState, useCallback } from 'react';
import { useFocusEffect } from '@react-navigation/native';

2. 替换原useEffect为useFocusEffect

useFocusEffect会在屏幕获得焦点时触发,完美匹配返回页面时清空内容的需求:

useFocusEffect(
  useCallback(() => {
    // 清空搜索输入、结果、错误信息
    setInput('');
    setResultRecords([]);
    setErrorMessage('');
    // 可选:重置选择器到默认选项、页码
    setSelected(options[0]);
    setCurrentPage(1);
  }, [])
);

3. 给输入框绑定状态值

修改AppTextInput组件,添加value属性实现UI与状态同步:

<AppTextInput
  placeholder="Search..."
  icon="magnify"
  onFieldChange={onInputChange}
  value={input || ''}
/>

4. 修复输入框状态更新逻辑

原onInputChange仅在输入非空时更新状态,导致清空输入框时状态不同步,修改为:

const onInputChange = (text) => {
  setInput(text);
  console.log('onInputChange: ', text);
};

修改后的完整代码(关键修改已标注)

import {
    StyleSheet,
    View,
    ActivityIndicator,
    FlatList,
    Button,
} from 'react-native';
import React, { useState, useCallback } from 'react';
import { useFocusEffect } from '@react-navigation/native'; // 新增导入
import AppTextInput from '../components/AppTextInput';
import Card from '../components/Card';

import colors from '../config/colors';

import axios from 'axios';
import { baseApiUrl, apikey } from '../api/config/apiLinks';
import AppPicker from '../components/AppPicker';
import AppText from '../components/AppText';
import { openBrowserAsync } from 'expo-web-browser';

const options = [
    { value: 'news', label: 'News' },
    { value: 'videos', label: 'Videos' },
    { value: 'documentaries', label: 'Documentaries' },
    { value: 'channels', label: 'Channels' },
];

export default function SearchScreen({ navigation }) {
    const [selected, setSelected] = useState(options[0]);
    const [input, setInput] = useState(''); // 初始值设为空字符串更合理

    const [resultRecords, setResultRecords] = useState([]);
    const [totalPages, setTotalPages] = useState();
    const [currentPage, setCurrentPage] = useState(1);
    const [errorMessage, setErrorMessage] = useState('');
    const [isLoading, setIsLoading] = useState(false);
    const [attachEnd, setAttachEnd] = useState(false);

    const url =
        baseApiUrl +
        '/search/search-get.php?' +
        apikey +
        '&category=' +
        selected.value +
        '&q=' +
        input +
        '&page=' +
        currentPage +
        '&count=15';

    const loadSearchResult = () => {
        setIsLoading(true);
        console.log('selected: ', selected.value);
        console.log('url: ', url);

        axios
            .get(url)
            .then((response) => {
                setErrorMessage(''); // 修复原代码设为0的错误,统一用空字符串表示无错误
                console.log(response);
                setTotalPages(response.data.totalPages);
                if (attachEnd) {
                    setResultRecords([...resultRecords, ...response.data.data]);
                } else {
                    setResultRecords(response.data.data);
                }
                setIsLoading(false);
                setAttachEnd(false);
                console.log('records: ', resultRecords);
            })
            .catch((error) => {
                if (error.response?.status == 404) { // 添加可选链避免undefined报错
                    setErrorMessage('Results not found!');
                }
                setIsLoading(false);
                console.log(error.response);
            });
    };

    const onInputChange = (text) => {
        setInput(text); // 移除非空判断,确保所有输入变化同步到状态
        console.log('onInputChange: ', text);
    };

    const renderLoader = () => {
        return isLoading ? (
            <View style={styles.loaderStyle}>
                <ActivityIndicator size="large" color="#aaa" />
            </View>
        ) : null;
    };

    // 替换原useEffect为useFocusEffect
    useFocusEffect(
        useCallback(() => {
            setInput('');
            setResultRecords([]);
            setErrorMessage('');
            setSelected(options[0]);
            setCurrentPage(1);
        }, [])
    );

    return (
        <View style={styles.container}>
            <View style={styles.innerContainer}>
                <AppTextInput
                    placeholder="Search..."
                    icon="magnify"
                    onFieldChange={onInputChange}
                    value={input || ''} // 新增value绑定
                />
            </View>
            <View style={styles.innerContainer}>
                <AppPicker
                    selectedItem={selected}
                    onSelectItem={(item) => setSelected(item)}
                    items={options}
                    icon="apps"
                    placeholder="Category"
                />
            </View>
            <View style={styles.button}>
                <Button title="Search" onPress={loadSearchResult} />
            </View>

            <View style={styles.results}>
                {errorMessage == '' && (
                    <FlatList
                        data={resultRecords}
                        keyExtractor={(records) => records.title}
                        renderItem={({ item }) => (
                            <Card
                                title={item.title}
                                feedName={item.feedName}
                                date={item.pubDate}
                                imageUrl={item.image}
                                onPress={() => {
                                    console.log('selectedOnPress: ', selected);
                                    console.log('browser: ', item.link);
                                    if (selected.value == 'news') {
                                        navigation.navigate(
                                            'NewsDetailsScreen',
                                            item
                                        );
                                    } else if (selected.value == 'videos') {
                                        navigation.navigate(
                                            'YoutubeVideoDetailsScreen',
                                            item
                                        );
                                    } else if (
                                        selected.value == 'documentaries'
                                    ) {
                                        openBrowserAsync(item.link);
                                    } else if (selected.value == 'channels') {
                                        openBrowserAsync(item.link);
                                    }
                                }}
                            />
                        )}
                        ListFooterComponent={renderLoader}
                    />
                )}
                {errorMessage != '' && (
                    <AppText style={styles.results}>{errorMessage}</AppText>
                )}
            </View>
        </View>
    );
}

const styles = StyleSheet.create({
    loaderStyle: {
        marginVertical: 16,
        alignItems: 'center',
    },
    container: {
        padding: 15,
        paddingBottom: 50,
        // backgroundColor: colors.light,
        flexDirection: 'column',
        width: '100%',
    },
    innerContainer: {
        width: '100%',
    },
    button: {
        width: '100%',
        marginTop: 15,
        marginBottom: 15,
    },
    results: {
        marginTop: 15,
        paddingBottom: 50,
        textAlign: 'center',
    },
});

额外说明

  • useFocusEffect是React Navigation专为屏幕焦点变化场景设计的钩子,比依赖navigation对象的useEffect更可靠
  • 输入框绑定value是受控组件的标准实现,确保UI始终与状态保持一致
  • 修复了setErrorMessage(0)的逻辑错误,统一用空字符串表示无错误状态
  • 添加error.response?.status可选链,避免请求失败时因response为undefined导致的报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 05:37:27