I don’t know about you, but React Native’s Layout and Flexbox model is confusing sometimes. That’s because it doesn’t always behave like it does in CSS. Really all you want is React Native text overflow to just wrap and call it a day. But it’s not so straightforward like that.
Lets wrap your head around flexWrap
In React Native, you may be tempted to try the flexWrap because it’s the only option with the word “wrap” in it. There’s even some people recommending using that style, but that style’s main concern is something else: it’s to break flexbox children, not text.
After some research, I found this GitHub issue.
Now, the solutions that were successful used the flexWrap option, but upon testing the flexWrap option was redundant. Some of the solutions used “flex: 1” on the parent view. I personally didn’t want to do that since that would negatively affect the layout of my app. I wanted my particular parent view to grow to the available space that was left.
If you understand “flex: 1” you’ll know that it’ll distribute the dimension in relationship to its siblings.
Lets say you do the following:
How flex works. It's not related to your muscles.
If you understand “flex: 1” you’ll know that it’ll distribute the dimension in relationship to its siblings.
Lets say you do the following:
import * as React from "react";
import {View} from "react-native";
One
Two
Three
Notice how there’s three children with “flex: 1”. In this case, the default flexbox direction is column (or vertical), so each children’s height will be distributed equally 1 + 2 + 1 = 4. So the first and last child takes 1/4th of the height, while the middle child gets 2/4ths of the height (or 1/2).
Going back to the text wrap issue in React Native. What I wanted to do was only have the text breaking and not affecting the overall flexbox layout. So in order to do that you’ll need to apply the “flex: 1” to the Text component itself, and for the parent you’ll add “flexDirection: row“.
Here’s how that looks like:
import * as React from 'react';
import { Text, View, SafeAreaView } from 'react-native';
export default function App() {
return (
One
Two very long text
Three
);
}
If you run the previous code you’ll see that it works just fine on native devices, but the text doesn’t wrap for web. So to fix that just add “width: 1” to the Text component like so.
Two very long text
The secret overflow sauce
It’s this specific combination of parent and child styles that break texts for both native devices and web. If you don’t want to add the “width: 1” across all platforms, you could just use “Platform.OS” and conditionally check for “web”.
So now lets see how that looks with the fix:
import * as React from 'react';
import { Text, View, SafeAreaView } from 'react-native';
export default function App() {
return (
One
Two very long text
Three
);
}
I’ve tried that in Brave (essentially Chrome), Safari, Firefox, and Microsoft Edge. They all accept the fix. It doesn’t seem like it’s something officially documented as I’ve tried to look up the W3 docs and there’s nothing that would allude to doing this. So consider this a “hack” just like back in the old days when we had to support IE 6+ ().
The only thing that I could assume here is that the flex width of the parent is growing to the full size of its child because of “flexGrow: 1” and then adding “width: 1” makes the flex child shrink less than the threshold causing “flexGrow: 1” to use the remainder of the width available from the parent container’s 160 total width. Basically 160 – 50 – 50 (container width minus the 2 views with 50) left us with 60 and that’s what flexGrow used instead of the intrinsic width of the text context which was longer than 60 units (px in web).
I hope this was useful to you and you’re able to create cross-platform React Native apps.