TextInput change inside a map function ReactNative

Viewed 32

I have a problem , each item as a TextInput (inside the map function )->

But when I changing the value of 1 input , ALL the values are changing. any solution ??

Here is my code :

          {order.currentShippingContent?.map((content, index) => {
            return (
              <View key={index} style={{marginTop:30}} >
                <View style={{}}
                  <Text style={styles.materialTypeText}>{content.material}</Text>
                  <View>
                    <TextInput
                    style={styles.InsertAmount}
                      keyboardAppearance="dark"
                      keyboardType="number-pad"
                      placeholder={"type amount"}
                      value={input}
                      onChangeText={(text) => { 
                        setInput(text);
                        if (Number(input) > Number(content.amount)) {
                          return alert("No such amount");
                        }
                        delivery.shippingContent[content.material] =
                          input;
                         
                      }}
                    />
                  </View>
                  <Text>/</Text>
                  <TextInput
                    style={styles.amountText}
                    placeholder={`${content.amount} `}
                    editable={false}
                  />
                </View>
              </View>
            );
          })}
2 Answers

The problem is in this line setInput(text);. So you have only useState and this value is used in all the TextInput. Your requirement is each of the TextInput should have their own useState.

You initialise useState with an object where each key and value will represent each TextInput and on change of the value from TextInput you should change that specific key value in the object

Each item needs its own state its own text input. The easiest way to give them their own state that I can think of is to use a FlatList. First create a function to render items:

const RenderItem = ({ content, index }) => {
    const [input, setInput] = useState('');
    return (
      <View style={{ marginTop: 30 }}>
        <Text style={styles.materialTypeText}>{content.material}</Text>
        <View style={{ flexDirection: 'row' }}>
          <TextInput
            style={styles.InsertAmount}
            keyboardAppearance="dark"
            keyboardType="number-pad"
            placeholder={'type'}
            value={input}
            onChangeText={(text) => {
              setInput(text);
              // setInput doesnt immediately update input
              // so just use text to avoid dealing with stale state
              if (Number(text || input) > Number(content.amount)) {
                return alert('No such amount');
              }
              delivery.shippingContent[content.material] = input;
            }}
          />
          <Text>/</Text>
          <TextInput
            style={styles.amountText}
            placeholder={`${content.amount} `}
            editable={false}
          />
        </View>
      </View>
    );
  };

And your flatlist:

<FlatList
        data={order.currentShippingContent || []}
        keyExtractor={({ item, index }) => index}
        renderItem={({ item, index }) => (
          <RenderItem content={item} index={index} delivery={delivery} />
        )}
      />
Related