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

