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

React Navigation Header中TextInput设useState初始值后无法输入

问题解决:React Navigation Header中自定义SearchBox输入被清空的问题

问题原因

你的代码中,navigation.setOptions仅在组件初始挂载时执行(useEffect依赖只有navigation),后续searchTerm、handleSearch、cleanSearch变化时,Header里的SearchBox无法获取最新的props,导致TextInput的value始终停留在初始值"",输入内容会被立刻重置。

解决方案

  1. 用useCallback包裹handleSearch和cleanSearch,稳定函数引用,避免每次渲染生成新函数引发不必要的setOptions调用。
  2. 将searchTerm、handleSearch、cleanSearch加入到useEffect的依赖数组中,确保这些值变化时,Header配置同步更新,让SearchBox拿到最新props。

修改后的代码

页面组件的Header配置部分

import { useCallback, useEffect, useState } from 'react';

// ...其他导入代码

const YourScreen = ({ navigation }) => {
    const [searchTerm, setSearchTerm] = useState("");
    const [toggleSearch, setToggleSearch] = useState(true)
    
    // 用useCallback缓存函数引用
    const handleSearch = useCallback(() => {
        setToggleSearch(prev => !prev);
    }, []);
    
    const cleanSearch = useCallback(() => {
        setSearchTerm("");
        setToggleSearch(prev => !prev);
    }, []);


    useEffect(() => {
        navigation.setOptions({
            headerShown: true,
            headerStyle: { backgroundColor: COLORS.lightWhite, height: 120 },
            headerLeft: () =>  <BackArrowWithText navigation={navigation} />,
            headerTitle: () => <View style={{overflow: 'hidden', alignItems: 'flex-end'}}>
                <SearchBox 
                    handleSearch={handleSearch} 
                    searchTerm={searchTerm} 
                    setSearchTerm={setSearchTerm} 
                    cleanSearch={cleanSearch} 
                />
            </View>,
            headerTitleAlign: 'left',
        })
    }, [navigation, searchTerm, handleSearch, cleanSearch]) // 添加必要依赖
    
    // ...页面其他逻辑代码
}

SearchBox组件(保持原代码即可)

import { useSharedValue, useAnimatedStyle, withTiming } from 'react-native-reanimated';
import { Ionicons } from '@expo/vector-icons';

const SearchBox = ({handleSearch, setSearchTerm, iconSize, cleanSearch, searchTerm}) => {
    const animation = useSharedValue(0);
    const animatedStyle = useAnimatedStyle(() => {
        return {
            width: withTiming(`${animation.value * 100}%`, {duration: 500}),
            borderWidth: withTiming(animation.value, {duration: 500}),
            paddingLeft: withTiming(animation.value * 10, {duration: 500})
        }
    })
    
    useEffect(() => {
        animation.value = 1;
    }, [])

    return (
        <Animated.View style={[styles.inputContainer, animatedStyle]}>
            <TextInput 
                style={styles.textInput}
                placeholder='Wpisz szukaną frazę'
                value={searchTerm}
                onChangeText={text => setSearchTerm(text)}
                onSubmitEditing={handleSearch} 
            />
            <View style={styles.collapseButtonContainer}>
                <TouchableOpacity onPress={cleanSearch}>
                    <Ionicons name={'close-outline'} size={iconSize ? iconSize : 24} color={COLORS.gray}/>
                </TouchableOpacity>
            </View>
        </Animated.View>
    )
}

补充说明

  • useCallback的作用是缓存函数引用,只有当依赖数组中的值变化时才会生成新函数,避免因函数引用变化导致useEffect频繁触发。
  • 把searchTerm加入依赖后,每次搜索词变化,Header里的SearchBox都会拿到最新的searchTerm值,TextInput就能正确显示输入内容,不会被清空。

内容的提问来源于stack exchange,提问作者Świętopeł Ziemowit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 13:32:47