【问题标题】:TextInput lost focus after typing one symbol when searching搜索时输入一个符号后 TextInput 失去焦点
【发布时间】:2018-04-07 11:26:46
【问题描述】:

我有一个平面列表

<View style={styles.container}>
    <FlatList data={this.state.restaurants} 
              renderItem={({ item }) => this.renderItem(item.restaurant)}
              keyExtractor={restaurant => restaurant.key}
              ListHeaderComponent={() => this.renderHeaderComponent()} 
              ItemSeparatorComponent={this.renderSeparator}/>
  </View>

并在标题中添加 TextInput。我使用 TextInput 作为搜索栏。

 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>
    );
  };

在 onChangeMethod 中过滤我的数据。

 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
    });
  }

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

【问题讨论】:

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


    【解决方案1】:

    我遇到了这个问题,为了解决这个问题,我将 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】:

      从 react-native 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>
      

      【讨论】:

        【解决方案3】:

        您需要为此使用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>
        )
        

        【讨论】:

        • 我遇到了完全相同的问题,但是(仅在 Android 上)这个解决方案很遗憾没有帮助......
        猜你喜欢
        • 2019-12-19
        • 1970-01-01
        • 1970-01-01
        • 2021-12-14
        • 2020-06-03
        • 2022-01-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多