Search code examples
javascriptreact-nativetextinput

React Native FlatList only gets updated when TextInput or Picker changes


I'm trying to dynamically add text from an input field and a picker to a FlatList in React Native. The problem I have is that the FlatList doesn't get updated as soon as I hit the button.

The item does get added to the list eventually but only after I trigger the onChangeText of the text input or the onValueChange of the picker element.

import React, { Component } from 'react';
import { View, Text, Picker } from 'react-native';
import { TextInput } from 'react-native-paper';
import { TouchableOpacity, FlatList, ScrollView } from 'react-native-gesture-handler';

CreateSetScreen = () => {
    const [value, onChangeText] = React.useState('Placeholder');
    const [pickerValue, setPickerValue] = React.useState("1");
    const [listValues, setListValue] = React.useState([]);
    
    joinData = () => {
        listValues.push({"content": value, "category": pickerValue, "key": listValues.length.toString()});
        setListValue(listValues);
    }

    return(
        <View>
            <TextInput 
                style={{height: 40, borderColor: 'gray', borderWidth: 1}}
                onChangeText={text => onChangeText(text)}
                value={value}
            />
            <Picker
                selectedValue={pickerValue}
                style={{height: 50}}
                onValueChange={(itemValue) => setPickerValue(itemValue)}
            >
                <Picker.Item label="Kategorie 1 - 1%" value="1" />
                <Picker.Item label="Kategorie 2 - 10%" value="2" />
                <Picker.Item label="Kategorie 3 - 20%" value="3" />
                <Picker.Item label="Kategorie 4 - 29%" value="4" />
                <Picker.Item label="Kategorie 5 - 40%" value="5" />
            </Picker>
            <TouchableOpacity
                style={{backgroundColor:'#DDDDDD'}}
                onPress={() => joinData()}
            >
            <Text>Add Item!</Text>
            </TouchableOpacity>
            <FlatList
                data={listValues}
                renderItem={({item}) => (<Text>{item.category}: {item.content}</Text>)}
            />
        </View>
    )
}
    

export default CreateSetScreen;

Any help is appreciated, thank you.


Solution

  • It seems .push() works in the setter function from React Hooks but It doesn't. Rather than returning the array itself, .push() returns the length of the array after modification.

    On the other hand, .concat() works to update state, that is .concat() creates a new array and then returns the changed array.

    So just change your joinData function a little bit in this way.

    const joinData = () => {
        setListValue(listValues => listValues.concat({ "content": value, "category": pickerValue, "key": listValues.length.toString() }));
    }