How to create a Read More component in React Native? - Startxlabs

How to create a Read More component in React Native?

We would have seen some apps that have some text display more shortly, revealing the full content only after clicking the “more” button. For example, we can see the big Instagram captions below the post only by clicking the “show more” option. Until it will display only a truncated text with fewer lines. We cannot display the whole text all the time. Sometimes we need a truncated version of the whole content. Do you think this less/more button is easy to develop? Absolutely not. Its implementation is somewhat complicated. So what can we do?

Since this display text is related to UI, it has to be implemented in such a way that it should be displayed efficiently in different screen sizes. So we can not just implement by adding a substring along with it and insert a button associated with it. We need to create a custom component for this. In this article, we will see how we can implement it.

Requirements

To achieve this, we need,

Read our article on  4 Most Common React Native Keyboard Issues

MoreLess Component

First, we need a text component that renders another component associated with the text. The moreless component is a functional component that takes 2 props such as truncatedText and fullText. It also has a state known as param and more and a function that updates it.

According to the text, the function helps in returning the text component that displays fullText or truncatedText. Its TouchableOpacity helps the user in toggling the “more” state.

OnTextLayout

Consider a situation, where we have to display the content or text in exact 3 lines for all the screen sizes. If the text is not exceeding the 3 lines, it can be displayed as such, and “more” button should not be added. But if the text exceeds the 3 lines, “more” button has to be added. By clicking on the “more” button, we will be able to see the full text. The revealed, full text will have a “less” button along with it. We achieve this by using the “onTextLayout” prop of the Text component.

Before

After

This onTextlayout event will tell us how many lines of the text should be displayed by the Text Component. Using this, we can capture the number of required states and save it on the state.

Read our article on Custom Tab Bar in React Native using SVG, and D3-Shape

Following is the code to achieve this.


import React, { useState } from "react";
import { View, Text, StyleSheet, ViewStyle } from "react-native";
import { colors } from "../utils/constants/colors";
import { fonts, fontSize } from "../utils/constants/fonts";
import { SCREEN_WIDTH } from "../utils/globalFunction";

interface PropTypes {
  text: string;
  containerStyle?: ViewStyle;
  targetLines?:number
}

const TextLessMoreView = (props: PropTypes) => {
  const [textShown, setTextShown] = useState(false); //To show your remaining Text
  const [lengthMore, setLengthMore] = useState(false); //to show the "Read more & Less Line"
  const [triggerTextLocation, setTriggerTextLocation] = useState({
    top: 0,
    right: 0,
  });

  const toggleNumberOfLines = () => {
    setTextShown(!textShown);
  };

  const onTextLayout = (e) => {
    const { lines } = e.nativeEvent;
    if (lines && Array.isArray(lines) && lines.length > 0) {
      let tempTxtLocaation = {
        top: (lines.length - 1) * lines[0].height,
        right: SCREEN_WIDTH - lines[lines.length - 1].width - 10,
      };
      setTriggerTextLocation(tempTxtLocaation);
      setLengthMore(lines.length >= props.targetLines);
    }
  };

  return (
    <View style={[styles.mainBody, props.containerStyle]}>
      <Text
        onTextLayout={onTextLayout}
        numberOfLines={textShown ? undefined : props.targetLines || 1}
        style={styles.txtStyle}
      >
        {props.text || ""}
      </Text>
      {lengthMore ? (
        <Text
          onPress={toggleNumberOfLines}
          style={[
            styles.lessMoreStyle,
            {
              position: "absolute",
              backgroundColor: colors.primary_background_color,
              right: triggerTextLocation.right,
              top: triggerTextLocation.top,
            },
          ]}
        >
          {textShown ? " less" : "... more"}
        </Text>
      ) : null}
    </View>
  );
};
const styles = StyleSheet.create({
  mainBody: {
    marginTop: 15,
  },
  txtStyle: {
    fontFamily: fonts.secondary_regular_font,
    fontSize: fontSize.modal_title_size,
    color: colors.white,
    flex: 1,
  },
  lessMoreStyle: {
    fontFamily: fonts.secondary_regular_font,
    fontSize: fontSize.modal_title_size,
    color: colors.app_orange,
  },
});
export default TextLessMoreView;

Usage –

Here this targetLines prop is used to define how many lines to be shown just before to see full content.

<TextLessMoreView
  text={"Text to be shown on screen"}
  targetLines={1}
/>

“We transform your idea into reality, reach out to us to discuss it.

Or wanna join our cool team email us at [email protected] or see careers at Startxlabs.”

Author: Akash Upadhyay

Share this blog