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

React Native Stack Navigation自定义Header共享及输入焦点异常解决

你推测的问题根因完全正确:当前配置下Stack导航器的每个页面都会单独创建一个NavigationBar实例,每个实例都有独立的query状态和输入框节点,页面切换后键盘焦点仍绑定在上个页面的输入框上,就会出现输入内容错位的问题。
下面提供两种可行的实现方案,优先推荐第一种:

方案1:全栈共用同一个Header(最优解)

直接把自定义Header放在Stack导航器外层,整个搜索栈只渲染一个Header实例,天然避免多实例问题,不需要额外做状态同步。
修改后的代码示例:

import { useNavigation } from '@react-navigation/native';
import { Keyboard, View } from 'react-native';
const Stack = createStackNavigator();

// NavigationBar接收上层传的搜索状态,自身不维护独立状态
function NavigationBar({query, setQuery}){
  const navigation = useNavigation();
  function deleteSearchQuery() : void {
      setQuery("");
  }

  return(
      <InputView>
          <BackIcon onPress={() => {
              navigation.goBack()
              Keyboard.dismiss()
          }}>
              <Icon name="arrow-back-ios" size={widthPercentage(24)} color="#666666"/>
          </BackIcon>
          <InputText
              keyboardType="default"
              maxLength={100}
              onChangeText={(str) => setQuery(str)}
              value={query}
              placeholder="검색어 입력"
              placeholderTextColor="#E9E9E9"
              returnKeyType="search"
              onFocus={() => navigation.navigate("SearchHistory")}
              onSubmitEditing={() => {
                navigation.navigate("SearchResult", { query })
                Keyboard.dismiss()
              }}
              allowFontScaling={false}
          />

          { query.length > 0 && 
              <DeleteIcon onPress={() => deleteSearchQuery()}>
                  <Icon name="clear" size={widthPercentage(20)} color="#666666"/>
              </DeleteIcon>
          }
          
          <SearchIcon onPress={() => {
              navigation.navigate("SearchResult", { query })
              Keyboard.dismiss()
          }}>
              <Icon name="search" size={widthPercentage(20)} color="#666666"/>
          </SearchIcon>

          <Line></Line>
      </InputView>
  );
}

export const Search = () =>{
  // 搜索状态提升到父组件维护,所有页面共用同一份状态
  const [query, setQuery] = React.useState('');
  return (
    <View style={{flex:1}}>
      {/* 公共Header放在Stack外层,全栈仅渲染一次 */}
      <NavigationBar query={query} setQuery={setQuery}/>
      <Stack.Navigator 
        initialRouteName="SearchMain" 
        keyboardHandlingEnabled={false}
        // 关闭导航器自带的Header,统一使用外层自定义Header
        screenOptions={{
          headerShown: false,
          animationEnabled: false
        }}
      >
          <Stack.Screen name="SearchMain" component={SearchMain} />
          <Stack.Screen name="SearchHistory" component={SearchHistory} />
          <Stack.Screen name="SearchResult" component={SearchResult} />
          <Stack.Screen name="SearchFilter" component={SearchFilter} />
      </Stack.Navigator>
    </View>
  );
}

export default Search;

如果子页面需要用到搜索关键词,直接通过route.params.query即可获取跳转时传入的参数。

方案2:多Header状态同步(仅当必须保留单页独立Header时使用)

如果业务需求必须每个页面单独渲染Header,可将搜索状态通过Context、Redux等全局状态管理工具存储,所有Header的输入值都绑定全局状态,修改时同步更新全局状态。同时需要给每个输入框加ref,页面挂载完成后主动调用当前页面输入框的focus()方法,切换焦点到当前输入框。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 02:54:02