H. Wynn
H. Wynn

Reputation: 493

React native text component using number of lines

Is there a way to determine when the text will be truncated when using number of lines ? Have been searching everywhere and no clear answer. Thank you!

Upvotes: 47

Views: 100628

Answers (4)

Théo Mesnil
Théo Mesnil

Reputation: 61

This works for me :)

import React, { useState } from 'react'

import { Text } from 'react-native'

export function MoreLessText({ children, numberOfLines }) {
  const [isTruncatedText, setIsTruncatedText] = useState(false)
  const [showMore, setShowMore] = useState(true)

  return isTruncatedText ? (
    <>
      <Text numberOfLines={showMore ? numberOfLines : 0}>{children}</Text>
      <Text onPress={() => setShowMore(!showMore)}>
        {showMore ? 'Read More' : 'Less'}
      </Text>
    </>
  ) : (
    <Text
      onTextLayout={(event) => {
        const { lines } = event.nativeEvent
        setIsTruncatedText(lines?.length > numberOfLines)
      }}
    >
      {children}
    </Text>
  )
}

Upvotes: 5

thethrdxer
thethrdxer

Reputation: 46

To create an instagram style comment with read more i did this (note that i'm using tailwind for styling, since this is a react-native app, the lib is nativewind, i'm also using a nested text which is allowing me to do a web html <span> element):

const [more, setMore] = useState(false)

const toggleShowMore = () => {
 setMore(!more)
}
<View className=" pl-1 pt-1 flex-row flex-1 max-w-[82%]">
    <Text numberOfLines={!more ? 3 : undefined}>
         <Text onPress={() => navigateUser(comment.user.username)} className="font-bold">
                @{comment.user?.username}{' '}
         </Text>{' '}
         <Text onPress={toggleShowMore}>{comment.content}</Text>
     </Text>
 </View>

Upvotes: 0

Arno
Arno

Reputation: 1001

This is now possible with the onTextLayout event that includes an array of lines being rendered out. Simply looking at the length you can determine if you are at the limit. There's other details in the lines array like actual height and width of every line which can be further used to determine if the text is being truncated.

const NUM_OF_LINES = 5;
const SOME_LONG_TEXT_BLOCK = 'Fill in some long text yourself ...';

return (<Text
  numberOfLines={NUM_OF_LINES}
  onTextLayout={({ nativeEvent: { lines } }) =>
    setState({ showMoreButton: lines.length === NUM_OF_LINES })
  }
>
  {SOME_LONG_TEXT_BLOCK}
</Text>;

Upvotes: 9

namth
namth

Reputation: 3117

You can use numberOfLines as a props for <Text /> component. Its depend on the width of your component then calculate the length of the text. This prop is commonly used with ellipsizeMode. Example:

<Text numberOfLines={2} ellipsizeMode='tail'>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</Text>

Upvotes: 97

Related Questions