skip to Main Content

How can I add a iterable index to my flatlist? In my SummaryCard component, I need to fire a function that tracks which SummaryCard is clicked, for example, "Summary Card vehicle 1 clicked", "summary vehicle 2 clicked".

  <FlatList
    data={data}
    contentContainerStyle={styles.list}
    renderItem={({ item }) => (
      <SummaryCard vehicle={item} key={item.vehicleId} />
    )}
    keyExtractor={(item) => item.vehicleId.toString()}
    ItemSeparatorComponent={() => <View style={styles.separator} />}
  />

4

Answers


  1. The data can be modified to have an index property. You can do this just after receiving the data.

    const indexedData= data.map((item, index) => ({
    ...item,
    index,
    }));
    

    Then you can modify your Flatlist component to use the modified data and can access the card number by item.index.

     <FlatList
    data={indexedData}
    contentContainerStyle={styles.list}
    renderItem={({ item }) => (
      <SummaryCard vehicle={item} key={item.vehicleId} />
    )}
    keyExtractor={(item) => item.vehicleId.toString()}
    ItemSeparatorComponent={() => <View style={styles.separator} />}
    />
    
    Login or Signup to reply.
  2. renderItem takes an object with three possible properties:

    1. item (Object): The item from data being rendered.
    2. index (number): The index corresponding to this item in the data array.
    3. separators (Object)
      • highlight (Function)
      • unhighlight (Function)
      • updateProps (Function)
        • select (enum(‘leading’, ‘trailing’))
        • newProps (Object)

    So you could write some code like this

    <FlatList
      data={data}
      contentContainerStyle={styles.list}
      renderItem={({ item, index }) => (
        <SummaryCard vehicle={item} vehicleIndex={index} key={item.vehicleId} />
      )}
      keyExtractor={(item) => item.vehicleId.toString()}
      ItemSeparatorComponent={() => <View style={styles.separator} />}
    />
    
    Login or Signup to reply.
  3. The second argument from renderItem is the index of the data passed to the FlatList.

    You simply need to do:

    <FlatList
      data={data}
      contentContainerStyle={styles.list}
      {/* Get index as second argument, and subsequently pass to SummaryCard */
      renderItem={({ item, index }) => (
        <SummaryCard vehicle={item} index={index} key={item.vehicleId} />
      )}
      keyExtractor={(item) => item.vehicleId.toString()}
      ItemSeparatorComponent={() => <View style={styles.separator} />}
    />
    
    Login or Signup to reply.
  4. It is possible to use the index argument inside the renderItem callback function.

    But indexes can eventually change if the list changes the size or content. As a solution to that you could consider tracking your clicked elements by id instead (or vehicleId). You can create some logic like this:

    const [selectedVehicles, setSelectedVehicles] = useState([]);
    
    const selectVehicle = (vehicleId) => {
      setSelectedVehicles((previousIds) => {
        if (previousIds.includes(vehicleId)) {
          return [...previousIds.filter((id) => id === vehicleId)];
        }
    
        return [...previousIds, vehicleId];
      })
    }
    
    return (
     <FlatList
        data={data}
        contentContainerStyle={styles.list}
        renderItem={({ item }) => (
          <SummaryCard
            vehicle={item}
            key={item.vehicleId}
            selected={selectedVehicles.includes(item.vehicleId)}
            onClick={() => selectVehicle(item.vehicleId)}
          />
        )}
        keyExtractor={(item) => item.vehicleId.toString()}
        ItemSeparatorComponent={() => <View style={styles.separator} />}
      />
    );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search