React-Native: Substitute for Flex-Basis

What's the equivalent of React Native { flex: 1 } for React JS?

React Native uses its own flexbox implementation - https://facebook.github.io/react-native/docs/flexbox

In React you are using CSS flexbox - https://developer.mozilla.org/en-US/docs/Glossary/Flexbox

Flexbox works the same way in React Native as it does in CSS on the web, with a few exceptions. The defaults are different, with flexDirection defaulting to column instead of row, and the flex parameter only supporting a single number.

In css, you also need to declare parent container as

.flex-container {
display: flex;
}

and that is probably what you are missing.

pure CSS version of your flex would probably look like this (styles as "string" version):

<div style="display: flex; flex-direction: column; height: 100vh;">
<div style="flex: 1; background-color: blue;">
<p>I'm a blue 50% screen View!</p>
</div>
<div style="flex: 1; background-color: yellow;">
<p>I'm a yellow 50% screen View!</p>
</div>
</div>

FlexBasis on React Native

If you set flex value on the surrounding View you will be able to see it

<View style={{flexDirection: 'row', justifyContent: 'space-between', flex: 1}}>
<View style={{flexGrow: 1, flexBasis:'0.5%', backgroundColor: 'rgba(129, 139, 196, 0.4)'}}></View>
<View style={{flexGrow: 1, flexBasis:'10%', backgroundColor: 'rgba(129, 139, 196, 0.5)'}}></View>
<View style={{flexGrow: 1, flexBasis:'50%', backgroundColor: 'rgba(129, 139, 196, 0.6)'}}></View>
<View style={{flexGrow: 1, flexBasis:'3%', backgroundColor: 'rgba(129, 139, 196, 0.7)'}}></View>
<View style={{flexGrow: 1, flexBasis:'2.5%', backgroundColor: 'rgba(129, 139, 196, 0.8)'}}></View>
<View style={{flexGrow: 1, flexBasis:'1.5%', backgroundColor: 'rgba(226, 7, 23, 0.5)'}}></View>
<View style={{flexGrow: 1, flexBasis:'2%', backgroundColor: 'rgba(226, 7, 23, 0.4)'}}></View>
<View style={{flexGrow: 1, flexBasis:'28.5%', backgroundColor: 'rgba(226, 7, 23, 0.3)'}}></View>
<View style={{flexGrow: 1, flexBasis:'0.5%', backgroundColor: 'rgba(226, 7, 23, 0.2)'}}></View>
<View style={{flexGrow: 1, flexBasis:'1.5%', backgroundColor: 'rgba(226, 7, 23, 0.1)'}}></View>
</View>

rendered output

react native flex 50% causes errors

Set up the container with flexDirection:'row' and each child to have half of the screen flexBasis without flex grow. something like this:

<View>
<View style={{flexDirection="row"}}>
<Image source={{uri:"http://image.com/image1.jpg"}} style={{flexBasis:Dimensions.get('window').width / 2, flexGrow:0}} resizeMode={"cover"} />
<Text {{flexBasis:Dimensions.get('window').width / 2, flexGrow:0}}>Picture 1</Text>
</View>
...

How can you ensure flex shrink in react-native (and how can you debug react-native styles in general)?

The proper solution to get the result you want is to add a flexBasis to the TabView like:

<TabView 
style={{ flexBasis: 0 }}
// rest of the code
/> ​

Why?
The TabView has a default style of flex: 1, overflow: 'hidden' (see source code) causing it to expanded to the size of its biggest child. The flexBasis prevents this and makes sure the tabview get the correct height.

Resource: This is a nice article about flexBasis vs width/height: https://mastery.games/post/the-difference-between-width-and-flex-basis/


Debugging styling in React-Native doesn't have the best developer experience. There are some things you can use to help you with debugging styling:

  • RN inspector: As Berci mentioned, React native has a dev menu where you can select "show inspector" that kinda acts like "inspect element" in a browser. It is a good tool to debug elements you can see, it also helps with debugging input/tab events.

  • Color: Most often I just use old fashioned colored borders & background to get a clear view of where elements are & their size/overlaps.

  • Comments & Simplify: Feel free to comment out components you're not interested in and replace complex components/views like ScrollCards with just a simple colored view. This can help prevent multiple behaviours from influencing the thing you're trying to debug

  • Browser inspect & React devtools: If you happen to run your RN app in the browser, then getting familiar with those tools will help you loads. Just keep in mind that React & React-Native isn't the same.

When you debug visuals, the best way is start at the top layer and work you way down. Color the elements & feel free to comment out elements to get you a clearer view of the problem. Keep digging down until you find the problem, don't be afraid to look into the source code of the packages you use, it often helps clarify (unexpected) behaviours.

flex vs flexGrow vs flexShrink vs flexBasis in React Native?

Here's some test code to consider:

render() {
return <View style={{flex: 1,backgroundColor: "cornflowerblue"}}>
<View style={{backgroundColor: "chartreuse"}}><Text>Nothing (17px)</Text></View>

<View style={{flex: 0, backgroundColor: "yellow"}}><Text>flex: 0 (17px)</Text></View>

<View style={{flex: 0, flexBasis: 10, backgroundColor: "brown"}}><Text>flex: 0, flexBasis: 10 (10px)</Text></View>
<View style={{flex: 0, flexGrow: 1, backgroundColor: "orange"}}><Text>flex: 0, flexGrow: 1 (97px)</Text></View>
<View style={{flex: 0, flexShrink: 1, backgroundColor: "tan"}}><Text>flex: 0, flexShrink: 1 (17px)</Text></View>
<View style={{flex: 0, flexGrow: 1, flexBasis: 10, backgroundColor: "purple"}}><Text>flex: 0, flexGrow: 1, flexBasis: 10 (90px)</Text></View>
<View style={{flex: 0, flexShrink: 1, flexBasis: 10, backgroundColor: "gray"}}><Text>flex: 0, flexShrink: 1, flexBasis: 10 (10px with 7px hidden below the next element)</Text></View>

<View style={{flex: 1, backgroundColor: "blue"}}><Text>flex: 1 (80px)</Text></View>

<View style={{flex: 1, flexBasis: 10, backgroundColor: "cornsilk"}}><Text>flex: 1, flexBasis: 10 (90px)</Text></View>
<View style={{flex: 1, flexGrow: 1, backgroundColor: "red"}}><Text>flex: 1, flexGrow: 1 (80px)</Text></View>
<View style={{flex: 1, flexShrink: 1, backgroundColor: "green"}}><Text>flex: 1, flexShrink: 1 (80px)</Text></View>
<View style={{flex: 1, flexGrow: 1, flexBasis: 10, backgroundColor: "aqua"}}><Text>flex: 1, flexGrow: 1, flexBasis: 10 (90px)</Text></View>
<View style={{flex: 1, flexShrink: 1, flexBasis: 10, backgroundColor: "pink"}}><Text>flex: 1, flexShrink: 1, flexBasis: 10 (90px)</Text></View>
</View>;
}

Here's a screenshot of the above code:

Screenshot

Added width and height:

render() {
return <View style={{flex: 1,backgroundColor: "cornflowerblue"}}>
<View style={{flex: 0, backgroundColor: "orange"}}><Text>flex: 0 (17px)</Text></View>
<View style={{flex: 0, width: 700, height: 20, backgroundColor: "yellow"}}><Text>flex: 0, width: 700, height: 20 (20px)</Text></View>

<View style={{flex: 0, flexBasis: 10, width: 700, height: 20, backgroundColor: "brown"}}><Text>flex: 0, flexBasis: 10, width: 700, height: 20 (10px with 7px hidden below the next element)</Text></View>
<View style={{flex: 0, flexGrow: 1, width: 700, height: 20, backgroundColor: "orange"}}><Text>flex: 0, flexGrow: 1, width: 700, height: 20 (90px)</Text></View>
<View style={{flex: 0, flexShrink: 1, width: 700, height: 20, backgroundColor: "tan"}}><Text>flex: 0, flexShrink: 1, width: 700, height: 20 (20px)</Text></View>
<View style={{flex: 0, flexGrow: 1, flexBasis: 10, width: 700, height: 20, backgroundColor: "purple"}}><Text>flex: 0, flexGrow: 1, flexBasis: 10, width: 700, height: 20 (80px)</Text></View>
<View style={{flex: 0, flexShrink: 1, flexBasis: 10, width: 700, height: 20, backgroundColor: "gray"}}><Text>flex: 0, flexShrink: 1, flexBasis: 10, width: 700, height: 20 (10px with 7px hidden below the next element)</Text></View>

<View style={{flex: 1, backgroundColor: "orange"}}><Text>flex: 1 (70px)</Text></View>
<View style={{flex: 1, width: 700, height: 20, backgroundColor: "blue"}}><Text>flex: 1, width: 700, height: 20 (70px)</Text></View>

<View style={{flex: 1, flexBasis: 10, width: 700, height: 20, backgroundColor: "cornsilk"}}><Text>flex: 1, flexBasis: 10, width: 700, height: 20 (80px)</Text></View>
<View style={{flex: 1, flexGrow: 1, width: 700, height: 20, backgroundColor: "red"}}><Text>flex: 1, flexGrow: 1, width: 700, height: 20 (70px)</Text></View>
<View style={{flex: 1, flexShrink: 1, width: 700, height: 20, backgroundColor: "green"}}><Text>flex: 1, flexShrink: 1, width: 700, height: 20 (70px)</Text></View>
<View style={{flex: 1, flexGrow: 1, flexBasis: 10, width: 700, height: 20, backgroundColor: "aqua"}}><Text>flex: 1, flexGrow: 1, flexBasis: 10, width: 700, height: 20 (80px)</Text></View>
<View style={{flex: 1, flexShrink: 1, flexBasis: 10, width: 700, height: 20, backgroundColor: "pink"}}><Text>flex: 1, flexShrink: 1, flexBasis: 10, width: 700, height: 20 (80px)</Text></View>
</View>;
}

Here's a screenshot of the above code:

Screenshot 2

flex: 0 (default)

  • flex: 0
    • Element takes the size of contents. According to the documentation it should be sized by setting width and height props but it seems to fit to contents if those aren't set.
  • flex: 0, flexBasis: {{px}}
    • Element takes the size given by flexBasis
  • flex: 0, flexGrow: 1
    • With flex: 0 and flexGrow: 1; it's the same as adding the size of the contents (in the example above it's a ) to the size of an element that's set to flex: 1. It's similar to flex: 1, flexBasis: 10 except instead of adding a number of pixels you're adding the size of the content.
  • flex: 0, flexShrink: 1
    • With flex: 0 and flexShrink: 1, the element seems to take the size of the content, in other words it's the same as just flex: 0. I'll bet there are situations where it would be bigger than the content but I haven't see that yet.
  • flex: 0, flexGrow: 1, flexBasis: {{px}}
    • This is the same as flex: 0, flexGrow: 1 except instead of adding the content size to a flex: 1 element it adds the given number of pixels.
  • flex: 0, flexShrink: 1, flexBasis: {{px}}
    • This is the same as flex: 0, flexBasis: {{px}}.
  • flex: 0, height: {{px}}
    • With flex: 0, height is treated just like flexBasis. If there is both a height and flexBasis are set, height is ignored.

flex: 1

  • flex: 1
    • Element takes available space. See Layout Props documentation for more details
  • flex: 1, flexBasis: {{px}}
    • With flex: 1 and flexBasis: {{px}}; the value of flexBasis is added to the element's size. In other words, it's like taking a flex: 1 element and adding on the number of pixels set by flexBasis. So if a flex: 1 element is 50px, and you add flexBasis: 20 the element will now be 70px.
  • flex: 1, flexGrow: 1
    • ignored
  • flex: 1, flexShrink: 1
    • ignored
  • flex: 1, flexGrow: 1, flexBasis: {{px}}
    • This is the same as flex: 1, flexBasis: {{px}} since flexGrow is ignored.
  • flex: 1, flexShrink: 1, flexBasis: {{px}}
    • This is the same as flex: 1, flexBasis: {{px}} since flexShrink is ignored.
  • flex: 1, height: {{px}}
    • With flex: 1, height is ignored. Use flexBasis instead.

Here are my observations:

  • Trouble Shooting Tip: Make sure the parent view(s) are giving the children room to grow/shrink. Notice the flex: 1 on the parent view, without it, all the children don't display as you'd expect.
  • Trouble Shooting Tip: Don't use Hot Reloading when testing these values, it can display elements incorrectly after it's reloaded a few times. I recommend enabling Live Reload or using command + r (a lot).
  • The default flex value is flex: 0. If you don't add a flex style value it defaults to 0.
  • Trouble Shooting Tip: if you're tryign to figure out why something isn't displaying like you think it should, start with the (most) parent element and make sure it's giving enough space to it's children to do what they need to do. In other words, try setting it to flex:1 and see if that helps, then go to the next child and repeat.
  • It seems like width is always considered with flexDirection: "column" no matter the other flex props. The same applies for height with flexDirection: "row".
  • After running these test, in general I would use flexBasis over height since flexBasis trumps height.

React-Native fill space

The answer is to add flex = 1. This will fill the remaining space.

<View style={ flex: 1 }}>
<View style={{ height: "10%" }}/>
{ probableView }

<View style={{flex: 1}}/> // Added here

<View style={{ height: "10%" }}/>
</View>

React-Native-Web Creates Automatic Classes for in-line Style and Applies Them in the Wrong Order

I figured it out.

After hounding the github issues for NextJS and react-native-web, I found this issue which describes the exact same problem.

The offending library was fixed years ago though. Through trial and error, and extensive use of this tool,

https://gist.github.com/necolas/8ee958917db65542784b60323ca6c4bc

I was able to narrow down the problem to this code. Removing it from the app fixed all CSS problems.

import { SafeAreaProvider } from 'react-native-safe-area-context'
<SafeAreaProvider>...</SafeAreaProvider>

Honestly, at this point I don't have any idea why I added SafeAreaProvider. It seems to be required for a non-native SafeAreaView. But the SafeAreaView built into RN + RN-Web is working fine for me.

If someone else has similar issues, I hope this answer will send you in the right direction.



Related Topics



Leave a reply



Submit