'How to show for text More/Less in React-Naitve (Javascript)
I am developing react-native application. In that, We are showing some description on Text, It may be number of lines.
So, If data has more than 3 lines, I have to show More and Less if it's expanded.
<FlatList
style={styles.faltList}
showsVerticalScrollIndicator
data={data}
extraData={this.state}
renderItem={({ item, index }) => (
<View style={styles.flatListCell}>
<Text style={styles.description}>{item.description}</Text>
</View>
</View>
)
}
ItemSeparatorComponent={() => (
<View style={{ height: 10}} />
)}
/>
I have found react-native-view-more-text library, But I would like to implement it by custom code.
Note: I am displaying that Text in Flatlist.
Any suggestions?
Solution 1:[1]
I tried in this way, Hope it helps to you and others!
const postTextContent = (props) => {
const [textShown, setTextShown] = useState(false); //To show ur remaining Text
const [lengthMore,setLengthMore] = useState(false); //to show the "Read more & Less Line"
const toggleNumberOfLines = () => { //To toggle the show text or hide it
setTextShown(!textShown);
}
const onTextLayout = useCallback(e =>{
setLengthMore(e.nativeEvent.lines.length >=4); //to check the text is more than 4 lines or not
// console.log(e.nativeEvent);
},[]);
return (
<View style={styles.mainContainer}>
<Text
onTextLayout={onTextLayout}
numberOfLines={textShown ? undefined : 4}
style={{ lineHeight: 21 }}>{Your Long Text}</Text>
{
lengthMore ? <Text
onPress={toggleNumberOfLines}
style={{ lineHeight: 21, marginTop: 10 }}>{textShown ? 'Read less...' : 'Read more...'}</Text>
:null
}
</View>
)
}
Solution 2:[2]
You can simply use numberOfLines, which is a <Text> prop:
Used to truncate the text with an ellipsis after computing the text layout, including line wrapping, such that the total number of lines does not exceed this number.
And, obviously, an adequate logic handler to save in your state which text is shown and which is truncated.
Let's see an example I've just created:
state = {
textShown: -1,
};
toggleNumberOfLines = index => {
this.setState({
textShown: this.state.textShown === index ? -1 : index,
});
};
render() {
return (
<View style={styles.container}>
<FlatList
data={[
{ key: 'a', description: longText },
{ key: 'b', description: longText },
{ key: 'c', description: longText },
]}
renderItem={({ item, index }) => (
<View style={styles.flatListCell}>
<Text
numberOfLines={this.state.textShown === index ? undefined : 3}
style={styles.description}>
{longText}
</Text>
<Text
onPress={() => this.toggleNumberOfLines(index)}
style={{ color: 'red' }}>
{this.state.textShown === index ? 'read less...' : 'read more...'}
</Text>
</View>
)}
/>
</View>
);
}
Here I use state to save the index of the element in the FlatList which is shown. If none is shown, then the value saved is -1.
You can try its behavior in this snack, that (I hope) reproduces your case. Let me know if this is what you're looking for. (Hi, Anilkumar, we've already met :) )
Solution 3:[3]
The first implementation is close but the problem is that the Read More button shows when the text equals 3 lines which it should not because there is no more text. I fixed it by updating the number of lines in state as well as checking if the text had been shown or not.
const ReadMoreText = ({ readMoreStyle, text, textStyle }) => {
const [showMoreButton, setShowMoreButton] = useState(false);
const [textShown, setTextShown] = useState(false);
const [numLines, setNumLines] = useState(undefined);
const toggleTextShown = () => {
setTextShown(!textShown);
};
useEffect(() => {
setNumLines(textShown ? undefined : 3);
}, [textShown]);
const onTextLayout = useCallback(
(e) => {
if (e.nativeEvent.lines.length > 3 && !textShown) {
setShowMoreButton(true);
setNumLines(3);
}
},
[textShown],
);
return (
<>
<Text onTextLayout={onTextLayout} numberOfLines={numLines} style={textStyle} ellipsizeMode="tail">
{text}
</Text>
{showMoreButton ? (
<Text onPress={toggleTextShown} style={readMoreStyle}>
{textShown ? 'Read Less' : 'Read More'}
</Text>
) : null}
</>
);
};
Solution 4:[4]
take a look over my solution, I did not use text lines, I used text length instead.
import React, {useState} from 'react';
import {Text, View, Image, TouchableOpacity, StyleSheet} from 'react-native';
const PostContent = () => {
const postDescription =
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
const [showMore, setShowMore] = useState(false);
return (
<View style={styles.postContentContainer}>
{postDescription.length > 120 ? (
showMore ? (
<TouchableOpacity onPress={() => setShowMore(!showMore)}>
<Text style={styles.postDescription}>{postDescription}</Text>
<Text style={styles.seeMore}>Show less</Text>
</TouchableOpacity>
) : (
<TouchableOpacity onPress={() => setShowMore(!showMore)}>
<Text style={styles.postDescription}>
{`${postDescription.slice(0, 120)}... `}
</Text>
<Text style={styles.seeMore}>Show more</Text>
</TouchableOpacity>
)
) : (
<Text style={styles.postDescription}>{postDescription}</Text>
)}
</View>
);
};
export default PostContent;
const styles = StyleSheet.create({
postContentContainer: {
// borderWidth: 1,
// borderColor: 'red',
flexDirection: 'column',
},
postMedia: {
//borderWidth: 1,
//borderColor: 'red',
width: '100%',
height: 280,
resizeMode: 'cover',
},
postDescription: {
paddingTop: 15,
paddingHorizontal: 15,
color: colors.text.black,
fontFamily: fonts.family.body,
fontSize: fonts.fontSizes.button,
fontWeight: fonts.fontWeights.thin,
},
seeMore: {
paddingHorizontal: 15,
color: colors.text.grey,
fontStyle: 'italic',
textDecorationLine: 'underline',
fontFamily: fonts.family.body,
fontSize: fonts.fontSizes.button,
fontWeight: fonts.fontWeights.thin,
},
});
Solution 5:[5]
A little late to the party, but I have developed a very optimal, lightweight solution to this. I call it react-native-more-or-less
Here is an example of how to use it:
import { MoreOrLess } from "react-native-more-or-less";
// ...
export default function App() {
return (
<MoreOrLess numberOfLines={3} textComponent={CustomText}>
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the
1500s, when an unknown printer took a galley of type and scrambled it to
make a type specimen book. It has survived not only five centuries, but
also the leap into electronic typesetting, remaining essentially
unchanged. It was popularised in the 1960s with the release of Letraset
sheets containing Lorem Ipsum passages, and more recently with desktop
publishing software like Aldus PageMaker including versions of Lorem
Ipsum.
</MoreOrLess>
);
}
Solution 6:[6]
import React from 'react';
import PropTypes from 'prop-types';
import AnchorText from '../AnchorText';
import { StyledContainer, RegularText } from './styles';
export default class Description extends React.Component {
constructor(props) {
super(props);
this.state = {
showMore: true,
};
}
onClick = () => {
this.setState({
showMore: false,
});
};
render() {
const { description } = this.props;
const { showMore } = this.state;
if (!description) return null;
return (
<StyledContainer FD={'column'}>
{showMore ? (
<RegularText MT={1}>
{description.slice(0, 150)}{' '}
{description.length > 150 && (
<AnchorText onClick={this.onClick} label=" .. Read more" />
)}{' '}
</RegularText>
) : (
<RegularText MT={1}>{description}</RegularText>
)}
</StyledContainer>
);
}
}
Description.propTypes = {
description: PropTypes.string,
};
Check out this Widget
Solution 7:[7]
state = {
textLenth: null,
numberOfLines: 3,
}
handleSeeMore = () => {
this.state.textLenth
? this.setState({numberOfLines: 0})
: this.setState({numberOfLines: 3});
};
<Text
numberOfLines={this.state.numberOfLines}
onPress={() => this.handleSeeMore()}
ellipsizeMode="middle"
onTextLayout={({nativeEvent: {lines}}) =>
this.setState({textLenth: lines.length === 3})
}>
This Gig Take a glance at the showcase of our artistic work:
Modern and Trendy Logo Artworkslkjfkljf ksnfksfnsf Mascot &
Custom Logo efdfg Artworks:lk knnk 'Explore the
ultimate Experience..!' To fulfill your designing needs,
Make us Graphically Yours...!! Why Team StrideInIt? We
believe in our
{' '}
{this.state.textLenth && (
<Text
color="red"
onPress={() => this.setState({numberOfLines: 0})}>
see more
</Text>
)}
</Text>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | 高鵬翔 |
| Solution 2 | Milore |
| Solution 3 | nanetteCodes |
| Solution 4 | Santiago Yepes |
| Solution 5 | Ren |
| Solution 6 | Aurangzaib Rana |
| Solution 7 | Cem |
