Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flex vs flexGrow vs flexShrink vs flexBasis in React Native?

I finally upgraded react native to 0.42 which includes the introduction of flexGrow, flexShrink, and flexBasis and the change (or fix) of how flex is rendered.

I keep getting errors like:

View was rendered with explicitly set width/height but with a 0 flexBasis. (This might be fixed by changing flex: to flexGrow:) View:

Can someone explain the difference between flex: 1 vs flexGrow: 1. If I apply one or the other to a View it seems to do different things but shouldn't it do the same?

like image 701
Dev01 Avatar asked Mar 31 '17 14:03

Dev01


People also ask

What is flexBasis in React Native?

Flex Basis, Grow, and Shrink​ Setting the flexBasis of a child is similar to setting the width of that child if its parent is a container with flexDirection: row or setting the height of a child if its parent is a container with flexDirection: column .

What are the differences between flexbox in the browser vs in React Native?

In React Native, Flexbox is the same as it is for basic CSS. The only difference being in default values. flexDirection: The default value for CSS is row whereas the default value in React Native is column. alignContent: The default value for CSS is stretch the default value in React Native is flex-start.

What does flex 1 mean React Native?

Normally you will use flex: 1 , which tells a component to fill all available space, shared evenly amongst other components with the same parent. The larger the flex given, the higher the ratio of space a component will take compared to its siblings.

What is the difference between Flex and Flex-grow?

flex is a shorthand property of flex-grow , flex-shrink and flex-basis . Then, the difference is that the flex base size will be 0 in the first case, so the flex items will have the same size after distributing free space.


1 Answers

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.
like image 153
Dev01 Avatar answered Oct 23 '22 06:10

Dev01