I'm running a RN app using native-base for styling. I have four elements on my homepage: a header, a tab view from vreact-native-tab-view
that contains a ScrollView
that takes up about 70% of the viewport, and two smaller 100% width
elements at the bottom.
However, the scrollview fills up more than 100% of the viewport and the two smaller elements get pushed to the bottom.
I looked in my element inspector and can apply a flexShrink to some of the many div
s, but I'm not sure which one that is in my code because it's div
hell when you use react-native. React devtools also has the same problem, except it's View
hell.
So, two questions:
For reference, here's how I've styled so far:
Home.tsx:
<View flex={1}> // applied a flex for the entire homepage
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
renderTabBar={renderTabBar}
onIndexChange={setIndex}
initialLayout={{ width: layout.width, height: "100%" }}
/>
<View width="100%">
<Center width="100%">
<StrengthSlider />
</Center>
<AdMobBanner
...props
/>
</View>
</View>
Teas.tsx:
<View flex={1} bg="white">
<ScrollCards teas={blackTeas} />
</View>
ScrollCards.tsx:
<ScrollView>
<Center>
{teas.length > 0 &&
teas.map((teaObj) => (
<TeaCard id={teaObj.id} teaData={teaObj.data} key={teaObj.id} />
))}
</Center>
</ScrollView>
EDIT:
Code Sandbox link: https://codesandbox.io/s/gracious-sammet-l4tqz?file=/src/App.js&resolutionWidth=402&resolutionHeight=675
Note that the admob footer remains underneath the cards content. It should be sticky and remain always at the bottom of the screen. I also noticed that when I'm not using the header from the MainStackNavigator
the footer works as intended - i.e. it remains sticky at the bottom - but I don't see why using the header (AppBar
) component should interfere with my footer.
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.
You could try to replace
<View flex={1}> // applied a flex for the entire homepage
in Home.tsx
with
<View flex="1 1 0">
Working example here (is your code with that line modified).
As for debugging I can only suggest what is already suggested on react native Debugging page. Have you tried React Developer Tools
yet? In chrome you can also add it as an extension from this link.
I am not sure if there is any difference between chrome extension and the npm package but the extension was enough for me at least (for now).
The only problem is that I also struggled debugging on codesandbox since the extension is definitely not working on javascript online editors (but probably the npm package doesn't either for this specific case)
Try this - https://snack.expo.dev/fL0OgQ9uS
import React from 'react';
import { View, Image, StyleSheet,ScrollView,Text } from 'react-native';
const styles = StyleSheet.create({
container: {
paddingTop: 50,
flex:1,
backgroundColor:'aqua',
},
tinyLogo: {
width: 200,
height: 200,
},
header:{
backgroundColor:'green',
paddingBottom:20,
},
footer:{
backgroundColor:'green',
paddingTop:20,
}
});
const DisplayAnImage = () => {
return (
<View style={styles.container}>
<View style={styles.header}><Text>header</Text></View>
<ScrollView>
<Image
style={styles.tinyLogo}
source={require('@expo/snack-static/react-native-logo.png')}
/>
<Image
style={styles.tinyLogo}
source={require('@expo/snack-static/react-native-logo.png')}
/>
<Image
style={styles.tinyLogo}
source={require('@expo/snack-static/react-native-logo.png')}
/>
<Image
style={styles.tinyLogo}
source={require('@expo/snack-static/react-native-logo.png')}
/>
<Image
style={styles.tinyLogo}
source={require('@expo/snack-static/react-native-logo.png')}
/>
<Image
style={styles.tinyLogo}
source={require('@expo/snack-static/react-native-logo.png')}
/>
<Image
style={styles.tinyLogo}
source={require('@expo/snack-static/react-native-logo.png')}
/>
</ScrollView>
<View style={styles.footer}><Text>footer</Text></View>
</View>
);
}
export default DisplayAnImage;