React Native中FlatList头部TextInput每输入一个字符键盘自动收起问题
问题原因
每次输入字符修改inputSearch状态时,父组件会触发重渲染,你当前直接给ListHeaderComponent传递了一个匿名函数作为渲染方法,每次重渲染都会生成全新的匿名函数实例,FlatList会判定头部组件需要完全更新,会销毁旧的头部组件实例再创建新实例,原来的TextInput会被卸载,自然就会失去焦点,键盘自动收起。
解决方案
下面是按优先级排序的可行修复方案:
- 方案1:将头部组件抽离为独立组件,直接传入JSX到
ListHeaderComponent,避免使用内联匿名函数
代码示例:
// 可以直接定义在当前组件外部,也可封装为单独的组件文件 const SearchHeader = ({ inputValue, onInputChange }) => { return ( <View style={{flexDirection:'column',justifyContent:'space-between'}}> <Text style={{color:Colors.dark1, fontSize:14, marginBottom: 5}}>Search :</Text> <TextInput style={styles.input} value={inputValue} onChangeText={onInputChange} placeholder="Username"/> </View> ) } // FlatList部分修改为 <FlatList contentContainerStyle={{alignItems: 'center',paddingHorizontal: 20}} keyExtractor={(item) => (Object.keys(item).length === 0) ? "empty-item" : item.id.toString()} width= {width} numColumns={2} ListHeaderComponent={<SearchHeader inputValue={inputSearch} onInputChange={setInputSearch} />} data={SIMPLE_DATA} renderItem={renderItemRow} />
- 方案2:如果需要保留函数形式的头部渲染方法,使用
useCallback包裹渲染函数,减少不必要的函数实例重建
代码示例:
// 在当前组件内部声明,依赖项仅添加必要变量 const renderHeader = useCallback(() => { return ( <View style={{flexDirection:'column',justifyContent:'space-between'}}> <Text style={{color:Colors.dark1, fontSize:14, marginBottom: 5}}>Search :</Text> <TextInput style={styles.input} value={inputSearch} onChangeText={setInputSearch} placeholder="Username"/> </View> ) }, [inputSearch, setInputSearch]) // FlatList部分修改为 ListHeaderComponent={renderHeader}
- 额外优化:修正
keyExtractor的返回值,不要返回空字符串作为列表项的key,空key会触发列表不必要的全局重渲染,可将空对象的key改为固定唯一值比如"empty-item"。 - 兜底方案:如果上述方法仍未解决,可以给FlatList添加
removeClippedSubviews={false}属性,关闭RN默认的视图裁剪回收逻辑,避免低版本RN中误回收输入框组件导致失焦。
内容的提问来源于stack exchange,提问作者Oussama Nm
相关产品推荐
相关产品推荐

