Home > Blockchain >  How to apply changes to a single element in a Flatlist in React Native
How to apply changes to a single element in a Flatlist in React Native

Time:05-01

I have a Flatlist that renders multiple posts, each post has a text section, the text can get very big so I'm using a show more method to expand/hide the text, and I'm handling the status of it using a state, however, when I click on a post to expand the text, it expands all posts in the Flatlist, I tried creating a dynamic Ref for each post, but I can't figure out a way to change the text content accordingly, anything I'm missing?

here's my code:

  const [showMore, setShowMore] = useState(false);

  const refs = useRef([]);




// Inside a Flatlist render item: 

    <View style={styles.postContainer}>
      {item.data.postText.length > 120 ? (
        showMore ? (
          <TouchableOpacity onPress={() => setShowMore(!showMore)}
           ref={(expandableText) => (refs.current[index] = expandableText)}>
            <Text style={styles.postDescription}>{item.data.postText}</Text>
            <Text style={styles.seeMore}>Show less</Text>
          </TouchableOpacity>
        ) : (
          <TouchableOpacity onPress={() => setShowMore(!showMore)}>
            <Text style={styles.postDescription}>
              {`${item.data.postText.slice(0, 120)}... `}
            </Text>
            <Text style={styles.seeMore}>Show more</Text>
          </TouchableOpacity>
        )
      ) : (
        <Text style={styles.postDescription}>{item.data.postText}</Text>
      )}
    </View>

CodePudding user response:

You are using the same state for all items of the FlatList. Hence, if you change the state, all items will be expanded. You could keep a boolean array as a state. The index of this state array corresponds to the index of a component inside the flatlist.

// data is the data of your FlatList
// we use this to initialize each show more value with false
const [showMore, setShowMore] = useState(data.map(data => false))

In your render function you use it as follows.

renderItem={({item, index}) => {
 return <View style={styles.postContainer}>
      {item.data.postText.length > 120 ? (
        showMore[index] ? (
          <TouchableOpacity onPress={() => handleShowMore(index)}
           ref={(expandableText) => (refs.current[index] = expandableText)}>
            <Text style={styles.postDescription}>{item.data.postText}</Text>
            <Text style={styles.seeMore}>Show less</Text>
          </TouchableOpacity>
        ) : (
          <TouchableOpacity onPress={() => handleShowMore(index)}>
            <Text style={styles.postDescription}>
              {`${item.data.postText.slice(0, 120)}... `}
            </Text>
            <Text style={styles.seeMore}>Show more</Text>
          </TouchableOpacity>
        )
      ) : (
        <Text style={styles.postDescription}>{item.data.postText}</Text>
      )}
    </View>
}

The handleShowMore function is as follows.

function handleShowMore(index) {
    setShowMore(prev => prev.map((element, idx) => {
        if(idx === index) {
            return !element
        }
        return element
   }))
}
  • Related