Search code examples
react-nativereact-native-flatlist

FlatList auto update or re-render react native


I am new to react native and I am stuck on this issue for 2 days now. I am trying to add a new item to my list which is given to Flatlist as a state. I read that FlatList is a pure component and it doesn't re-render itself unless it is told via "extraData" and also when the value of state is changed the component re-renders itself but these two options don't seem to work for me. Clearly, I am doing something wrong or my concepts are not clear. Have a look at my code.

import { StatusBar } from 'expo-status-bar';
import React,{useState, useEffect} from 'react';
import { StyleSheet, Text, View, TouchableOpacity, FlatList, SafeAreaView, ToastAndroid } from 'react-native';



export default function App() {

  var dishList = [
    {
      id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
      title: 'First Item',
    },
    {
      id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
      title: 'Second Item',
    },
    {
      id: '58694a0f-3da1-471f-bd96-145571e29d72',
      title: 'Third Item',
    },
  ]
  const [dishes, setDishes] = useState(dishList)
  var count = 0;

  useEffect(()=>{
    console.log("use")
  },[dishes])

  const CustomDish = (props) => {
    return(
      <View style={styles.item}>
        <TouchableOpacity  >
          <Text style={styles.title}>{props.title} = {props.id}</Text>
        </TouchableOpacity>
      </View>
    )
  };

  const renderItem = ({ item }) => (
    <CustomDish title={item.title} id={item.id} />
  );

  function addItem(){
    count = count + 1;
    console.log("Count: "+ count)
    var i = {
      id: `${count}`,
      title: `${count + " Item"}`,
    }
    dishList.push(i)
    setDishes(dishList)
    console.log("state length: "+ dishes.length)
    console.log("list length: "+ dishList.length)
    
  }

  function renderScreen(){
    return(
      <View style={styles.container}>
      <StatusBar style="auto" />
      <View style={{backgroundColor: 'blue', flex:1,width:'100%', height:"100%"}}>
        <SafeAreaView style={{margin: 20}} >
          <FlatList
            data={dishes}
            renderItem={renderItem}
            keyExtractor={item => item.id}
          />
      </SafeAreaView>
      </View>
      <View style={{flexDirection: 'row'}}>
        <TouchableOpacity style={styles.button} onPress={addItem} >
          <Text style={styles.buttonText} >Add</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.button} >
          <Text style={styles.buttonText} >Remove</Text>
        </TouchableOpacity>
      </View>
    </View>
    )
  }

  return (
    <SafeAreaView style={styles.container}>
      {renderScreen()}
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  button:{alignSelf: 'auto',backgroundColor: 'red', height: 50, width: 100, justifyContent:"center", margin: 10},
  buttonText:{alignSelf: 'center', fontWeight: 'bold'},
  item: {
    backgroundColor: '#f9c2ff',
    padding: 20,
    marginVertical: 8,
    marginHorizontal: 16,
  },
  title: {
    fontSize: 20,
  },

});

What I am trying to do here is to press the "Add" button and add a new item to my list and also show a view to represent that it is added to the list. so in console.log the value of my list and state does update, its length does change from 3 to 4 and 4 to 5 and so on each time I press the button but on the screen, the FlatList doesn't render any new components, please help.


Solution

  • You need to do this

    function addItem() {
        count = count + 1;
        console.log("Count: " + count);
        var i = {
            id: `${count}`,
            title: `${count + " Item"}`,
        }
        let dishTemp = [...dishes];
        dishTemp.push(i);
        setDishes(dishTemp);
        console.log("state length: " + dishes.length);
        console.log("list length: " + dishList.length);
    }