Trouble on adding items to Flatlist, React Native

Tags: , , , ,



DIET (screen)

export class Diet extends Component {
  constructor(props) {
    super(props);
this.state = {
foodList: [],
    };
  }
    render() {
      return (
           <View>
                  <List>
                    <FlatList
                      data={this.props.route?.params?.foodList}
                      keyExtractor={(item, index) => item.key.toString()}
                      renderItem={(data) => (
                        <ListItem>
                          <Button>
                            <Left>
                              <Text>{data.item.foodName}</Text>
                            </Left>
                            <Right>
                              <Text>{data.item.calories}</Text>
                              <Icon name="arrow-forward" />
                            </Right>
                          </Button>
                        </ListItem>
                      )}
                    />
                  </List>
                </View>

FOODCREATE (screen)

export class FoodCreate extends Component {
  constructor(props) {
    super(props);
    this.state = {
      food: null,
      calories: null,
      foodList: [],
    };
  }

  submitFood = (food, calories) => {
    this.setState(
      {
        foodList: [
          ...this.state.foodList,
          {
            key: Math.random(),
            foodName: food,
            calories: calories,
          },
        ],
      },
      () => {
        this.props.navigation.navigate("Diet", {
          foodList: this.state.foodList,
        });
      }
    );
  };
render() {
    return (
      <Container>
         <TextInput
            placeholder="Food Name"
            placeholderTextColor="white"
            style={styles.inptFood}
            value={this.state.food}
            onChangeText={(food) => this.setState({ food })}
          />
         <TextInput
            placeholder="Calories"
            placeholderTextColor="white"
            style={styles.inptMacros}
            keyboardType="numeric"
            value={this.state.calories}
            maxLength={5}
            onChangeText={(calories) => this.setState({ calories })}
          />
          <Button transparent>
          <Icon
            name="checkmark"
            style={{ fontSize: 25, color: "red" }}
            onPress={() => {
              this.submitFood(this.state.food, this.state.calories);
            }}
          />
        </Button>

Hello everyone, I’m trying to make an app in which the user has to insert foodName and calories in the FoodCreate screen and once he taps the checkmark it will add the foodName and calories to the Flatlist in the Diet screen (when I launch Expo the first screen to appear is the Diet screen). When I insert the first food item everything goes fine, but when I want to insert another one, the one I inserted before disappears and it shows only the one I just inserted. I don’t know if it’s a problem related with the Flatlist or React Navigation. But the Flatlist won’t keep the items I inserted.

Answer

The problem here is the way navigation works, Everytime you open the FoodCreate screen the the component is mounted again and the FoodList is reset, so the newly added one would be the only item there, you return this as a parameter to Diet screen which will show only one item.

Heres a the better way to do it.

Move the state management to Diet screen

class Diet extends Component {
  constructor(props) {
    super(props);

    this.state = {
      foodList: [],
    };
  }
 
 // Use this to update state.
  static getDerivedStateFromProps(props, state) {
    if (props.route.params?.food) {
      return { foodList: [...state.foodList, props.route.params.food] };
    }
    return null;
  }

And show the value in the state in the flatlist

 <FlatList data={this.state.foodList} ...

Change submitFood like below to send only newly created item

submitFood = (food, calories) => {
 
        this.props.navigation.navigate("Diet", {
          food: {
            key: Math.random(),
            foodName: food,
            calories: calories,
          },
        });
  }

The easier way is to switch to functional components, you can refer the documentation here https://reactnavigation.org/docs/params/#passing-params-to-a-previous-screen



Source: stackoverflow