在搜索时键入一个符号后,TextInput失去了焦点

时间:2017-10-26 07:29:04

标签: javascript reactjs react-native redux react-redux

我有一个FlatList

 renderHeaderComponent() {
    return(
      <View style={{ flexDirection: 'row', marginTop: 10, borderBottomColor: '#CED0CE', borderWidth: 1, borderColor: 'transparent' }}>
        <Icon name='search' size={30} style={{ marginLeft: 10, marginRight: 10 }}/>
        <TextInput
            style={{height: 40, flex: 1}}
            onChangeText={(text) => this.onChangeText(text)}
            placeholder='Type text for search'
            clearButtonMode='while-editing'
            value={this.state.searchText}
      />
      </View>
    );
  };

在标题中有TextInput。我使用TextInput作为搜索栏。

 onChangeText(text) {
    const filteredRestaurants = _.filter(this.props.list, (restaurantObject) => {
      const restaurant = restaurantObject.restaurant;
      const result = restaurant.name.trim().toLowerCase().includes(text.trim().toLowerCase());
      return result;
    })
    this.setState({
      searchText: text,
      restaurants: filteredRestaurants
    });
  }

在onChangeMethod我过滤我的数据。

{{1}}

问题如下。当我在TextInput中键入一个符号时,焦点会立即从TextInput丢失?键入时如何将焦点保持在TextInput中?

3 个答案:

答案 0 :(得分:2)

您需要使用auto-bound方法,因为ListHeaderComponent的类型为ReactClass,您当前的方法基本上会重新创建并重新绑定其render每次数据更新,这不是你想要的。 this comment

进一步解释了这一概念

无论如何,对于你的例子,你应该

解决你的问题

1)将ListHeaderComponent道具改为

ListHeaderComponent={this.renderListHeader}

2)现在您要将renderHeaderComponent方法更改为auto-bound method,并且通过这样做,每次更改数据时都不会实例化新的渲染(或者将文本输入到`TextInput中)

renderListHeader = () => (
  <View style={{ flexDirection: 'row', marginTop: 10, borderBottomColor: '#CED0CE', borderWidth: 1, borderColor: 'transparent' }}>
      <Icon name='search' size={30} style={{ marginLeft: 10, marginRight: 10 }}/>
      <TextInput
          style={{height: 40, flex: 1}}
          onChangeText={(text) => this.onChangeText(text)}
          placeholder='Type text for search'
          clearButtonMode='while-editing'
          value={this.state.searchText}
      />
  </View>
)

答案 1 :(得分:2)

我遇到了这个问题,为了解决这个问题,我将 renderListHeader 包装在 React.useMemo 钩子中,并将状态钩子作为一个项目传递给依赖数组。

 renderListHeader = useMemo(() => (
  <View style={{ flexDirection: 'row', marginTop: 10, borderBottomColor: '#CED0CE', borderWidth: 1, borderColor: 'transparent' }}>
      <Icon name='search' size={30} style={{ marginLeft: 10, marginRight: 10 }}/>
      <TextInput
          style={{height: 40, flex: 1}}
          onChangeText={(text) => this.onChangeText(text)}
          placeholder='Type text for search'
          clearButtonMode='while-editing'
          value={this.state.searchText}
      />
  </View>
), [this.onChangeText])

答案 2 :(得分:1)

从本地版本0.61.5开始,这仍然是SectionList的问题。 auto-bound方法不起作用,因为当数据变为空数组时,ListHeaderComponent重新呈现。

我使用了以下解决方法:

  1. 将文本输入代码移动到与节列表相同的级别
  2. 使用绝对位置,将其放置在所需位置。
  3. 将其包装在Animated.View
  4. 利用Animated.event将Y转换为Animated.View

代码示例

const animatedScrollYValue = useRef(new Animated.Value(0)).current;
...
<View>
  <Animated.View style={{
    position: 'absolute',
    top: 142,
    left: 30,
    right: 30,
    zIndex: 1,
    transform: [{ translateY: Animated.multiply(animatedScrollYValue, new Animated.Value(-1)) }] }}>
    // Your text input
  </Animated.View>
  <Animated.SectionList
    scrollEventThrottle={1}
    onScroll={Animated.event([{ nativeEvent: { contentOffset: { y: animatedScrollYValue } } }], { useNativeDriver: true })}
    keyExtractor={(item) => item.id}
    ListHeaderComponent={// Whatever you want but make you include space for the absolute TextInput}
    sections={data}
    renderItem={renderItem}
    renderSectionHeader={renderHeader}
  />
</View>