Home > Software design >  React Native - How to display first label fully and hide second label when it is < certain width?
React Native - How to display first label fully and hide second label when it is < certain width?

Time:12-21

I have two views with texts inside, acting like labels. These labels are put inside a card view with a fixed width. I want the first label to always be fully visible regardless of length of text, as much as possible.

To achieve this, the second label should be shortened as much as possible with Ellipsis Mode and FlexShrink but once the second label is shortened such that its width is < 25 px, I want to hide it.

enter image description here

What I've tried:

  1. The method I have right now is to read the width of the second label using onTextLayout and hide accordingly, but I'm not sure if there's a better way to achieve this effect, hopefully purely with styling.

  2. I have also tried TextWrap then hiding the second row but it wraps as long as both tags exceed the width - I want the second label to shorten as much as possible first, before wrapping.

Current Code Setup

const [showLabel, setShowLabel] = React.useState(true);

...

return (
    <View style={styles.tagsContainer}>
        {labels.slice(0, 2).map((tag: string, index: number) => {
            if (index === 1 && !showLabel) {
                return;
            }

            return (
                <View
                    key={index}
                    style={[styles.tagWrapper,{flexShrink: index,}]}
                >
                    <Text
                        style={styles.tag}
                        numberOfLines={1}
                        onTextLayout={(e) => {
                            if (index === 1 && e.nativeEvent.lines[0].width < 17) {
                                setShowLabel(false);
                            }
                        }}
                    >
                        {tag}
                    </Text>
                </View>
            );
        })}
    </View>;
)

const TAG_HEIGHT = 15
const styles = StyleSheet.create({
    tagsContainer: {
        flexDirection: 'row',
        minHeight: TAG_HEIGHT,
      },
    tagWrapper: {
        minHeight: TAG_HEIGHT,
        alignItems: 'center',
        borderWidth: 0.5,
        marginRight: 4,
        paddingHorizontal: 2,
      },
    tag: {
        ...font(10, 'regular'),
        lineHeight: 14,
    },
})

ps. Does using useState make this component stateful? That's probably not encouraged?

CodePudding user response:

There's nothing inherently wrong about your current solution. There are other ways:

  • conditionally render the second View based on the width of the outer View. You can measure the width using the outer View's onLayout prop: onLayout={({ nativeEvent }) => setWidth(nativeEvent.layout.width)}
  • measure the width the same way, but set the size of your .slice instead based on the result

Yes, using useState makes the component stateful, but there's nothing bad about that. State is a good tool to hold local data like this.

  • Related