Oleksandr Fomin
Oleksandr Fomin

Reputation: 2356

Handling Show More/Less text in React Native

I'm getting a response from a remote API in HTML format. The whole thing is not supposed to be shown unless you press Read More button The response looks as follows:

"<p>A suspension concentrate (SC) formulation containing 450 g/litre of napropamide (41.4% w/w) for the control of annual grass and broad-leaved weeds in winter oilseed rape.</p>\r\n<p><strong>DIRECTIONS FOR USE</strong><br /> IMPORTANT: This information is approved as part of the product label. All instructions within this section must be read carefully in order to obtain safe and successful use of this product.</p>\r\n<p><strong>RESTRICTION/WARNINGS</strong><br /> Weed control may be reduced where the spray is mixed too deeply into the soil. <br />Do not treat crops adversely affected by poor soil, adverse weather or cultural conditions. <br />Avoid spray overlap, particularly on headlands. <br />It is important to ensure that the seedbed is free from clods and weeds, and in good tilth.<br /> Incorporation under wet conditions is not satisfactory. <br />AC650 can be used on a wide range of soils but should not be applied to Sands (ADAS &rsquo;85 system)
...

I render it using react-native-render-html library which unfortunately does not have numberOfLines prop.

I tried a solution suggested on Github that involves adding custom renderer that substitutes all the <p> tags with react native <Text> tag which has numberOfLines props that I need:

<HTML
   html={`<p>${description}</p>`}
   renderers={{p: (_, children) => <Text numberOfLines={5}>{children}</Text>}}
/>

It worked but the problem is that I have several <p> tags inside my description variable and it shows all of them shortened to whatever number of lines I entered instead of shortening the whole article. So I figured that I must use a unique tag to wrap the whole HTML content and then apply the same logic

<HTML
  html={`<section>${description}</section>`}
  renderers={{section: (_, children) => <Text>{children}</Text>}}
/>

Again, the solution worked but it messed up the content inside. Line breaks were not applied, etc.

After a few more Google searches up stumbled upon a 3rd party library called react-native-read-more-text I understand that it only works with content inside <Text> tag so once again I wrapped by <Text> using template string

<ReadMore
  numberOfLines={10}
  renderTruncatedFooter={renderTruncatedFooter}
  renderRevealedFooter={renderRevealedFooter}>
    <HTML
    html={`<Text>${description}</Text>`}
    />
</ReadMore>

This time I received an error:

enter image description here

I would appreciate any help

Upvotes: 1

Views: 4881

Answers (2)

Ravendarksky
Ravendarksky

Reputation: 633

This is now supported by react-native-render-html

import HTML from 'react-native-render-html'; // V6.3.4

const defaultTextProps = {
    numberOfLines: 10,
  };

  return (
    <HTML
      source={{ html: text }}
      defaultTextProps={defaultTextProps}
    />
  );

Github Issue

I hope this helps. I would be interested to know what you went with in the end as I am currently solving a similar use case.

Upvotes: 6

Jules Sam. Randolph
Jules Sam. Randolph

Reputation: 4230

My suggestion would rather be not to mess-up with react-native-render-html, and instead do the following:

  • wrap your HTML content inside a container which height approximates 5 lines;
  • this container has a fading effect towards its bottom (typical in user-review platforms such as Goodreads);
  • at the bottom of this container, a "read more" button can be pressed to expand the container height to fit the html content height.

If however you need one tag renderer in peculiar to implement such feature, you should take a look at this SO post: https://stackoverflow.com/a/69200348/2779871

Upvotes: 3

Related Questions