0

I have a list of many items where each item has TextInput and TouchableOpacity wrapped by View. I've trying to set focus on TextInput in the list item in which TouchableOpacity has been pressed. It's needed for editing each item's name.

Below is the code of how I tried to do this. The problem of this code is that after pressing on any of the TouchableOpacity the last TextInput will always be focused due to the fact that the last iteration overwrites textInputRef.

Is there a way to make textInputRef contain a reference to the TextInput which TouchableOpacity will press?

   const ListComponent = ({list}) => {
    const textInputValue = useRef('');
    const textInputRef = useRef(null);

    changeItemName = (text) => {
     textInputValue.current = text;
    };

    return (
      <ScrollView>
        {list.length > 0 &&
          list.map((item) => (
            <View key={item._id}>
              <TouchableOpacity>
                <View
                  <Text>{`Item: `}</Text>
                  <TextInput ref={textInputRef} onChangeText={changeItemName}>
                    {item.name}
                  </TextInput>
                </View>
              </TouchableOpacity>
              <TouchableOpacity
                onPress={() => {
                  textInputValue.current = '';
                }}>
                <Icon name={'check'} size={25} color="#000" />
              </TouchableOpacity>
              <View>
                <TouchableOpacity
                  onPress={() => {
                    textInputValue.current = item.name;
                    textInputRef.current.focus();
                  }}>
                  <Icon name={'edit'} size={25} color="#000" />
                </TouchableOpacity>
              </View>
            </View>
          ))}
      </ScrollView>
    );
  };
Nafaz M N M
  • 1,558
  • 2
  • 27
  • 41
A. Norvag
  • 19
  • 3
  • 6
  • 1
    See https://stackoverflow.com/questions/55995760/how-to-add-refs-dynamically-with-react-hooks – D10S Jul 14 '20 at 13:46
  • @D10S I think this might worked, but I'm not sure if this is a good performance solution for a large list. – A. Norvag Jul 14 '20 at 14:52
  • I don't think it should change much the performance as adding a ref to an item is not cunsuming that much. If it is really large then you should use VirtualizedList like 'FlatList'. – D10S Jul 14 '20 at 16:00

1 Answers1

1

I think creating an array of ref will help you to resolve.

Try this way

const ListComponent = ({list}) => {
    const textInputValue = useRef('');
    const textInputRef = useRef(null);

    changeItemName = (text) => {
     textInputValue.current = text;
    };

    const collectionRef = useRef(list.map(() => createRef()));

    return (
      <ScrollView>
        {list.length > 0 &&
          list.map((item, index) => (
            <View key={item._id}>
              <TouchableOpacity>
                <View
                  <Text>{`Item: `}</Text>
                  <TextInput ref={collectionRef.current[index]} onChangeText={changeItemName}>
                    {item.name}
                  </TextInput>
                </View>
              </TouchableOpacity>
              <TouchableOpacity
                onPress={() => {
                  textInputValue.current = '';
                }}>
                <Icon name={'check'} size={25} color="#000" />
              </TouchableOpacity>
              <View>
                <TouchableOpacity
                  onPress={() => {
                    textInputValue.current = item.name;
                    collectionRef[index].current.focus();
                  }}>
                  <Icon name={'edit'} size={25} color="#000" />
                </TouchableOpacity>
              </View>
            </View>
          ))}
      </ScrollView>
    );
  };
Chanuka Sandeepa
  • 680
  • 6
  • 10