Thursday 19 August 2021

Newly created TextInputs in FlatList lose focus after 10th row - initialNumToRender

I'm attempting to build a To-Do list feature for an application; however, I'm struggling to get it right.

Basically, I want a user to be able to create new list items via the "submit" key while typing, or a button (both already done). When the new list item is created, I want the corresponding TextInput within the FlatList to be automatically focused. This works...up to a certain point. Once I create 10 list items, the behavior stops working properly and the focus is no longer on the next, newly created FlatList item.

I've figured out that if I change the "initialNumToRender" property in the FlatList and increase it past 10, it will solve the problem, temporarily, until reaching that cap. However, I don't want to reduce the performance of my FlatList and I want to find a different solution. It seems to me that the entire FlatList is re-rendering past 10 items and the TextInput loses focus, but I haven't been able to grasp yet how to focus on the TextInputs created after the 10th row.

The FlatList in question:

      <FlatList
        key="flatlist"
        ListHeaderComponent={listHeader()}
        initialNumToRender={10}
        data={listItems}
        // TODO: Will need to change to use actual IDs at some point as opposed to just indexing
        renderItem={({item, index}) => (
          <>
            <View style={listStyles.itemView}>
              <Pressable onPress={() => radioButtonPressed(index)}>
                <MainListRadioButton completed={getRadioButtonState(index)} />
              </Pressable>
              {listItems[index].text.length > 0 ? (
                <TextInput
                  style={listStyles.itemText}
                  placeholder={`Item ${index + 1}`}
                  defaultValue={listItems[index].text}
                  value={listItems[index].text}
                  onChangeText={text => listItemTextChanged(text, index)}
                  ref={index === listItems.length - 1 ? lastListItemRef : null}
                  onSubmitEditing={() => addListItem()}
                />
              ) : (
                // Text input for "empty" list items so that a backspace can delete the entire row.
                <TextInput
                  style={listStyles.itemText}
                  placeholder={`Item ${index + 1}`}
                  defaultValue={listItems[index].text}
                  value={listItems[index].text}
                  onChangeText={text => listItemTextChanged(text, index)}
                  ref={index === listItems.length - 1 ? lastListItemRef : null}
                  onKeyPress={({nativeEvent}) => {
                    if (nativeEvent.key === 'Backspace') {
                      deleteListItem(index);
                    }
                  }}
                />
              )}
            </View>
            <View style={styles.divider} />
          </>
        )}
      />

How I'm implementing the behavior to shift focus to the next row so far:

  useEffect(() => {
    if (lastListItemRef.current) {
      lastListItemRef.current.focus();
    }
  }, [listItems]);


from Newly created TextInputs in FlatList lose focus after 10th row - initialNumToRender

No comments:

Post a Comment