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?
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:
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:
flex: 0
(default)
flex: 0
- Element takes the size of contents. According to the documentation it should be sized by setting
width
andheight
props but it seems to fit to contents if those aren't set.
- Element takes the size of contents. According to the documentation it should be sized by setting
flex: 0, flexBasis: {{px}}
- Element takes the size given by
flexBasis
- Element takes the size given by
flex: 0, flexGrow: 1
- With
flex: 0
andflexGrow: 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 toflex: 1
. It's similar toflex: 1, flexBasis: 10
except instead of adding a number of pixels you're adding the size of the content.
- With
flex: 0, flexShrink: 1
- With
flex: 0
andflexShrink: 1
, the element seems to take the size of the content, in other words it's the same as justflex: 0
. I'll bet there are situations where it would be bigger than the content but I haven't see that yet.
- With
flex: 0, flexGrow: 1, flexBasis: {{px}}
- This is the same as
flex: 0, flexGrow: 1
except instead of adding the content size to aflex: 1
element it adds the given number of pixels.
- This is the same as
flex: 0, flexShrink: 1, flexBasis: {{px}}
- This is the same as
flex: 0, flexBasis: {{px}}
.
- This is the same as
flex: 0, height: {{px}}
- With
flex: 0
,height
is treated just likeflexBasis
. If there is both aheight
andflexBasis
are set,height
is ignored.
- With
flex: 1
flex: 1
- Element takes available space. See Layout Props documentation for more details
flex: 1, flexBasis: {{px}}
- With
flex: 1
andflexBasis: {{px}}
; the value offlexBasis
is added to the element's size. In other words, it's like taking aflex: 1
element and adding on the number of pixels set byflexBasis
. So if aflex: 1
element is 50px, and you addflexBasis: 20
the element will now be 70px.
- With
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}}
sinceflexGrow
is ignored.
- This is the same as
flex: 1, flexShrink: 1, flexBasis: {{px}}
- This is the same as
flex: 1, flexBasis: {{px}}
sinceflexShrink
is ignored.
- This is the same as
flex: 1, height: {{px}}
- With
flex: 1
,height
is ignored. UseflexBasis
instead.
- With
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 enablingLive 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 withflexDirection: "column"
no matter the other flex props. The same applies forheight
withflexDirection: "row"
. - After running these test, in general I would use
flexBasis
overheight
sinceflexBasis
trumpsheight
.
来源:https://stackoverflow.com/questions/43143258/flex-vs-flexgrow-vs-flexshrink-vs-flexbasis-in-react-native