Search code examples
react-nativereact-hooksreact-native-flatlistuse-contextflatlist

Flatlist doesn't display the list from useContext


In react native app, I have a home screen and a second screen that the user uses to add items that should be displayed on the home screen. I am using context to save the list of items. The problem is when I add items to the second screen and go to the home screen. The displayed list is empty.

Any help to explain why this happens and how to handle it? Here's the Data Context export const ExpenseContext = createContext();

App.js

const Stack = createNativeStackNavigator();
function App() {
  const [expenseList, setExpenseList] = useState([]);
  return (
    <NavigationContainer>
      <ExpenseContext.Provider value={{ expenseList, setExpenseList }}>
        <Stack.Navigator>
          <Stack.Screen
            name="Home"
            component={Home}
            options={{ title: "Dashboard" }}
          />
          <Stack.Screen
            name="AddItem"
            component={AddItem}
            options={{ title: "CashFlowCreate" }}
          />
        </Stack.Navigator>
      </ExpenseContext.Provider>
    </NavigationContainer>
  );
}
export default App;

Home.js

function Home({ route, navigation }) {
  const { expenseList } = useContext(ExpenseContext);
  return (
    <View style={styles.container}>
      <Text style={styles.text}>Budget:</Text>
      <Button title="+" onPress={() => navigation.navigate("AddItem")} />
      <View>
        <FlatList
          style={styles.listContainer}
          data={expenseList}
          renderItem={(data) => <Text>{data.item.name}</Text>}
        />
      </View>
    </View>
  );
}
export default Home;

AddItem.js

function AddItem({ navigation }) {
  const { expenseList, setExpenseList } = useContext(ExpenseContext);
  const [name, setName] = useState("");
  const [amount, setAmount] = useState("");
  const itemsList = expenseList;
  return (
    <View style={styles.container}>
      <TextInput
        style={styles.input}
        onChangeText={(name) => setName( name )}
        value={name}
        placeholder="Name"
        keyboardType="default"
      />
      {name === "" && (
        <Text style={{ color: "red", fontSize: 12, paddingLeft: 12 }}>
          Name is required
        </Text>
      )}
      <TextInput
        style={styles.input}
        onChangeText={(amount) => setAmount( amount )}
        value={amount}
        placeholder="Amount"
        keyboardType="numeric"
      />
      {amount === "" && (
        <Text style={{ color: "red", fontSize: 12, paddingLeft: 12 }}>
          Amount is required
        </Text>
      )}
      
      <Button
        title="Add"
        style={styles.btn}
        onPress={() => {
          if (name === "" || amount === "") {
            alert("Please Enter the required values.");
          } else {
            itemsList.push({
              name: name,
              amount: amount,
            });
            setExpenseList(itemsList);
          }
        }}
      />
      <Button
        title="View Dashboard"
        style={styles.btn}
        onPress={() => {
          navigation.navigate("Home");
        }}
      />
    </View>
  );
}

export default AddItem;

Solution

  • I solve it, in AddItem component remove const itemsList = expenseList; and onPress add button it should be like that instead

     onPress={() => {
              name === "" || amount === ""
                ? alert("Please Enter the required values.")
                : setExpenseList([
                    ...expenseList,
                    {
                      key:
                        Date.now().toString(36) +
                        Math.random().toString(36).substr(2),
                      name: name,
                      amount: amount,
                    },
                  ]);
            }}
    

    I added the key because I needed later on.