scrollview and flatlist override loading view - react-native

I have got flatlist inside scrollview and its working fine, but both going over the loading view so I got blank view while first loading which contain both of them while first run loading.
I didn't find any questions on it.
<ScrollView style={{ backgroundColor: 'white', padding: scale(5) }} contentContainerStyle={{}}
// scrollEventThrottle={this.onScroll}
>
<FlatList style={{ transform: [{ scaleX: -1 }], borderBottomWidth:1, borderBottomColor: '#eee'}} contentContainerStyle={{ justifyContent: 'center', paddingBottom: !dataFollowing ? scale(40) : scale(20), alignItems: 'flex-start', backgroundColor: 'white', paddingHorizontal: scale(10) }} horizontal data={allData}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
ListHeaderComponent={
<TouchableOpacity onPress={() => {
this.props.navigation.navigate('Search');
}}>
</FlatList></ScrollView>
so basically I see this
scrollview over loading

As per i worked with this, i figured out that there is no need to use ScrollView as FlatList is Scrollable . If you are using FlatList inside ScrollView then it throw some warning.
This also happened same with me while using Loader with them so try :
Create a state and give boolean value and in the render you would create tenrary condition (?:) .
For example data is coming from API , so if data is not fetched the isLoading state is true and Loader is running and as soon as data is fetched then setState isLoading to false and Flatlist data is rendering.
If it doesn't clear or not matched with your question then please try to elaborate more i will help surely.

Related

react-native-keyboard-aware-scroll-view : Page scrolls down when I start typing

Until typing everything is ok. However after starting typing page scrolls down(shifting). I am not able to solve this whatever i do...
<ImageBackground
source={bgSrc}
style={styles.background}
resizeMode="cover">
<StatusBar hidden={true} />
<KeyboardAwareScrollView
showsVerticalScrollIndicator={false}
enableOnAndroid
>
{screenToShow}
</KeyboardAwareScrollView>
</ImageBackground>
const styles = StyleSheet.create({
container: {
width: '100%',
height: height,
backgroundColor: '#555',
},
background: {
flex: 1,
width: null,
height: null,
justifyContent: 'center',
alignItems: 'center'
}
});
before typing, it's looking perfect
After typing in the password field page moves down as u see:
after typing, it scroll down
This library is always a bit janky. Try a configuration like this:
<KeyboardAwareScrollView
style={{ backgroundColor:
themeColors.boxPrimaryBackground, flexGrow: 1 }}
contentContainerStyle={{ width: '100%', margin: 0 }}
scrollEnabled={true}
extraScrollHeight={-125}
extraHeight={10}
keyboardOpeningTime={Number.MAX_SAFE_INTEGER}
showsVerticalScrollIndicator={false}
keyboardShouldPersistTaps={'handled'}
>
// add scroll content here
</ KeyboardAwareScrollView>
The thing you really need to add is the keyboardOpeningTime={Number.MAX_SAFE_INTEGER}. It has something to do with the animation inside the library. Good luck hope this helps.
I have seen your question on github as well, and its been a long time since that is in open state there.
I have the above problem resolved using KeyboardAvoidingView from react-native
import {KeyboardAvoidingView} from 'react-native'
I have replaced KeyboardAwareScrollView with KeyboardAvoidingView and this is working as needed.
Here is an app link that does this. You can download and see it's login page.

React Native FlatList rendering a few items at a time

I have a list of chat messages in my app to which new items are added to the bottom. I used some code from another SO question to make the FlatList stick to the bottom when new items are added, as below
<FlatList
data={messages}
renderItem={({item}) => <ChatMessage message={item}></ChatMessage>}
keyExtractor={(item, index) => index.toString()}
initialNumToRender={messages.length}
initialScrollIndex={messages.length-1}
ref={ref => this.flatList = ref}
onContentSizeChange={(contentWidth, contentHeight)=>{
this.flatList.scrollToEnd();
}}
/>
The problem is that when the initial list renders (only 35 items, hardcoded in an array for now) it seems to render just a few items, then scroll down a bit, then render a few more, then scroll down a bit until it finally completes the rendering and sticks to the bottom. It's choppy and slow, despite adding initialNumToRender={messages.length} and rendering an incredibly simple node for each result.
Ideally I guess I need to wait for it to fully render before displaying anything to the user but (A) they'd have to wait a couple of seconds to start using the chat room and (B) I don't think that's how Flatlist works, I assume the elements have to be viewable before it is rendered.
Is there just a better way to do this? (Testing on Android by the way)
EDIT: Adding ChatMessage component for completeness
// Chat Message
import React, { Component } from 'react'
import {
StyleSheet,
ImageBackground,
Text,
View
} from 'react-native'
class ChatMessage extends Component {
constructor(props) {
super(props)
this.state = { }
}
render() {
return (
<View style={styles.chatMessage}>
<View style={styles.chatMessage_layout}>
<View style={styles.chatMessage_pic}>
<View style={styles.chatMessage_pic_image}>
<ImageBackground
source={require('./assets/images/profile-pics/example-profilr.png')}
style={styles.chatMessage_pic_image_background}
imageStyle={{ borderRadius: 40/2 }}
resizeMode="cover"
>
</ImageBackground>
</View>
</View>
<View style={styles.chatMessage_details}>
<View style={styles.chatMessage_name}>
<Text style={styles.chatMessage_name_text}>
{this.props.message.name}
<Text style={styles.chatMessage_name_time}> 24h</Text>
</Text>
</View>
<View style={styles.chatMessage_message}>
<Text style={styles.chatMessage_message_text}>{this.props.message.text}</Text>
</View>
</View>
</View>
</View>
)
}
}
export default ChatMessage;
const styles = StyleSheet.create({
chatMessage: {
paddingVertical: 10,
paddingHorizontal: 24
},
chatMessage_layout: {
flexDirection: 'row'
},
chatMessage_pic: {
width: 40,
height: 40,
marginRight: 12
},
chatMessage_pic_image: {
width: 40,
height: 40
},
chatMessage_pic_image_background: {
width: 40,
height: 40
},
chatMessage_details: {
flex: 1
},
chatMessage_name_text: {
color: '#FFF',
fontSize: 14,
fontWeight: 'bold'
},
chatMessage_name_time: {
fontSize: 11,
color: 'rgba(255,255,255,0.6)'
},
chatMessage_message: {
flexDirection: 'row',
alignItems: 'center'
},
chatMessage_message_text: {
color: '#FFF',
fontSize: 12
}
})
If you have less number of items and want to render all items at once then you should use ScrollView as mentioned in the docs
ScrollView: Renders all elements at once, but slow if there are large number of elements.
FlatList: Renders items in a lazy mode, when they are about to appear and removes them when they leave the visible display to save memory that makes it usable for performance on large lists.
For Flatlist optimization you need to use PureComponent whenever you render the child so that it only shallow compares the props.
Also in the keyExtractor use a unique id for your item and do not depend upon the index, since when the item updates the index is not reliable and may change

width: '100%' vs Dimension.get('window').width in react native

I'm new to react native and css styling as a whole so sorry if the question is very basic. I want a view to take 100% of the available screen width and when i use the code below my view seems to go outside the screen boundry, though when I use Dimension.get('window').width it work just fine. can someone explain how they differ from each other. any help would be really appreciated. thanks
return(
<TouchableOpacity style = {styles.food_wrapper}
onPress = {()=> this.userAction()}
>
<Text style = {styles.foodname}>
{this.name}
</Text>
<Text style = {styles.foodprice}>
Rs: {this.price}
</Text>
</TouchableOpacity>
);
food_wrapper:{
flex: 1,
flexDirection :'row',
justifyContent:'space-between',
alignItems:'flex-start',
width: '100%',//Dimensions.get('window').width,
minHeight: 50,
marginVertical: '1%',
padding: '2%',
backgroundColor: 'rgb(155,200,200)'
},
You need to understand what is the basic difference from 100% and the width you get using dimension.get('window')
100% means you want to get the container 100% width which mean if your parent container is 50px then 100% will return 50px.
the width from dimension give you a static width of your device width
so be careful to choose what to use to your component
if you want to follow the parent container then it is easier to use 100% then width from dimension but for responsive reasons without any parent container or it is the parent itself then width from dimension will work better
You need to add a wrapper view with flexDirection: 'row', then style the child view (or Touchable or whatever) with flex: 1
<View style={{ flexDirection: 'row' }}>
<View style={{ flex: 1, height: 100, backgroundColor: 'grey' }} />
</View>
Or you could use alignSelf: 'stretch' inside a few with flexDirection: 'column' (which is the default for all views)
Hang in there. Learning flexbox takes some practice. Your first thought when you get stuck should be "do I need to add a wrapper view?"

React-Native fixed Footer within ScrollView?

I would like to create Views with dynamic content that should have some kind of footer that should normally (if there is enough space) look like they are sticked to the bottom.
Before I introduced ScrollViews my code looked like this:
<View style={{flex: 1, justifyContent: 'space-between'}}>
<View>{content}</View>
<View>{stickyFooter}</View>
</View>
After introducing the ScrollView I had to remove flex: 1 because otherwise the ScrollView is not scrollable at all. After that justifyContent became useless because the height of the flex-container is not set to 100%. Therefore both Views just appear next to each other.
To make clear what my view should look like in general:
The button should not be sticked to the bottom, but it should appear at the bottom (if possible).
This is an old question now, but for the benefit of those who end up here from a google search like I did, I paste the solution that worked for me below.
Markup
render = () => {
return (
<View>
<ScrollView style={styles.container}>
...
</ScrollView>
<TouchableOpacity style={styles.floatingActionButton}>
<RkButton
rkType='stretch'>
<RkText>Do stuff</RkText>
</RkButton>
</TouchableOpacity>
</View>
)
}
Styles
const styles = StyleSheet.create(theme => ({
floatingActionButton: {
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
bottom: 10,
left: 10,
right: 10,
borderRadius: 10,
}
}));

Why my react native navigation bar's text not on the vertical center?

I use the Navigator.NavigationBar component to make a navbar, but the text not vertical centering.
Like this:
How can I solve this?
I just ran into this issue too. The solution:
<Navigator.NavigationBar
routeMapper={{
Title: (route, navigator, index, navState) =>
{
return (
<View style={{
justifyContent: 'center',
flex: 1
}}>
<Text style={{color: 'white'}}>Candidates</Text>
</View>
);
},
}}
/>
So basically make sure there's a parent wrap on your navbar elements filling the navbars height (the flex: 1 rule) and vertically center its contents with justifyContent: 'center'.
I've done the styles inline for this example, but of course it'd be more efficient to get those from a StyleSheet object.