React Native FlatList refreshing not working - javascript

i got an problem with the refreshing on pull function. The FlatList renders fine, but pull to refresh is not working. This is my current sourcecode:
return (
<View style={GlobalStyles.flex1}>
<FlatList
showsVerticalScrollIndicator={false}
refreshControl={
<RefreshControl
refreshing={isRefreshing}
onRefresh={() => {
console.log("onRefresh loadVocable");
loadVocables();
}}
/>
}
data={vocables}
keyExtractor={vocable => vocable.id}
onEndReached={() => {
if (!isRefreshing && !endReached) {
loadVocables();
}
}}
renderItem={vocable => (
<TouchableOpacity
onPress={() => {
props.navigation.navigate({ routeName: "editVocable", params: { vocable: vocable.item } });
}}
onLongPress={() => {
handleLongPress(vocable.item.id);
}}>
<Card style={styles.cardStyle}>
<View style={styles.part1}>
<Text style={styles.vocableText}>{vocable.item.wordENG}</Text>
<Text style={styles.vocableText}>{vocable.item.wordDE}</Text>
</View>
<View style={styles.part2}>
<Ionicons name={vocable.item.known ? "md-checkmark-circle" : "md-close-circle"} size={23} color={vocable.item.known ? Colors.success : Colors.danger} />
</View>
</Card>
</TouchableOpacity>
)}
/>
</View>
);
In the official docs is an example that says contentContainerStyle needs to be flex: 1 to know the height, that makes sence to me, so when i set contentContainerStyle with flex 1, refresh on pull works fine, but then i can't scroll anymore in the Flatlist and everthing get very tight, so the style also change then. Does anyone know why this happen?
The first picture is with "contentContainerStyle={{flex: 1}}" and the last one is without contentContainerStyle.

The answer was so easy, I compared a new project (there worked my code) to the one where the problem was and after 5 days I found the little error:
My import was wrong!
I imported FlatList like this:
import { FlatList } from "react-native-gesture-handler";
But it needs to get imported from React-Native so like this:
import { FlatList } from "react-native";
Thanks to #The1993, without the hint to compare the projects, maybe I would stuck forever on this error :D In the future I will compare working files to find any error!

contentContainerStyle is used to style inner content e.g items alignments, padding, etc
style is used to align its height and relations
You can replace style={{flex: 1}} instead of contentContainerStyle or wrap the parent element with flex: 1

Related

How to add custom component inside an Flatlist in React Native?

I have a Flatlist on react native by which its working perfectly, recently saw an UI which has a custom designed compoenent in between the list, kindly check the below reference image
Check this image, a new design named "Safety+" has been added inside an list, How to do this ?
Need to add custom design like below randomly inside and already rendered flatlist ! How to achieve this , as i couldn't find or understand where to start
Please check the image and help in achieving this:
<FlatList
contentContainerStyle={{ paddingBottom: 50 }}
data={this.state.availableBusList}
keyExtractor={item => item.id}
renderItem={({item}) => {
return(
<TouchableOpacity style={styles.busCardContainer}
onPress={() => {
console.log(item);
//this.props.navigation.navigate('SeatLayout')
}}
<Text>{item.name}</Text>
>)}}
/>
This is my flatlist code
You can return a fragment with your component and a randomly included component. The condition for inclusion is up to you, i.e. complete chance, every 5th element, etc.
<FlatList
contentContainerStyle={{ paddingBottom: 50 }}
data={this.state.availableBusList}
keyExtractor={item => item.id}
renderItem={({item}) => {
return(
<Fragment>
<TouchableOpacity style={styles.busCardContainer}
onPress={() => {
console.log(item);
//this.props.navigation.navigate('SeatLayout')
}}
>
<Text>{item.name}</Text>
</TouchableOpacity>
{Math.random() < 0.5 && ( // example 50% chance to include random component
<RandomComponent>...</RandomComponent>
)}
</Fragment>
)}}
/>
You can render conditionally in your renderItem function: https://reactjs.org/docs/conditional-rendering.html
Additionally, if you want to render your custom component at specific indexes, you can also put index parameter into renderItem. Here is my example:
<FlatList
contentContainerStyle={{ paddingBottom: 50 }}
data={this.state.availableBusList}
keyExtractor={item => item.id}
renderItem={({ item, index }) => {
return index % 5 === 0 ? <CustomComponent /> : <NormalComponent />;
}}
/>

React Native: Make a view take the whole screen when other view is not present

This may seem like a basic question, but I can't seem to figure it out or properly word a search on this.
I have a View with two other Views in it, one of which sometimes is hidden. So the component looks something like this:
function MyComponent (props) {
return (
<View style={{ flex: 1 }}>
{
props.showButtonView
? (
<View style={{ flex: ??? }}>
<Button title='do something' onPress={() => console.warn('doSomethign)} />
</View>
)
: null
}
<View style={{ flex: ?? }}>
<Stuff/>
</View>
</View>
)
}
Now, what I am trying to do is have the Stuff component cover the entire screen whenever the Button is not present. However, if the props.showButtonView is true, and we do want to see the view with the Button I only want need to see the button on the top, and then the rest is
whatever is in the Stuff component. How do I get this done? Is it based on the flex numbers?
Also, you may be wondering why I need to separate these two into separate Views in the first place, the reason for that is because there are other unrelated things in the Stuff component that cover the button and don't allow me to click it. Anyway, long story short, the separation of the two by View is mandatory for this case.
flex should be 1 for both the places.
Flex:1 Indicates that it will takes the whole space available after if. So, it doesn't really matters when a button is placed there or not. Whenprops.showButtonView is true then the button is at the top and rest your stuff is placed after that.
Otherwise,
When props.showButtonView is false then button render code will not be executed and then stuff view will be all over your
Try below code when props.showButtonView === true
function MyComponent (props) {
return (
<View style={{ flex: 1 }}>
{
props.showButtonView
? (
<View style={{ width: '100%' }}>
<Button title='do something' onPress={() => console.warn('doSomethign)} />
</View>
)
: null
}
<View style={{ flex: 1 }}>
<Stuff/>
</View>
</View>
)
}

Scroll area too small with SectionList React Native

I am currently trying to use a <SectionList> inside a classic <View>, all my datas are formatted, the list displays correctly and my item's actions are working.
The issue is that when I am on the top of my SectionList, the area available to trigger the scroll is actually really small ( roughly 100 pixels from the top of the list ). However, once i scroll down a bit from that area, the whole list becomes scrollable and works as intended until I scroll back to the top.
My parent View has flex: 1 as well as my SectionList
Environment
Working environment : MacOS Sierra 10.13.3
Expo version : 23.0
React Native version : 0.50
React : 16.0
Using an IPhone 8 simulation
There's no issue on Android
Steps to Reproduce
Classic creation of a SectionList inside of a View
Expected Behavior
The scroll must be triggered from everywhere in the SectionList
Actual Behavior
When the SectionList is at the top, the scroll only triggers inside a small area ( around 100px from the top of the list )
The code of my SectionList :
<View style={{ flex: 1 }}>
<SectionList
style={styles.openSectionList} // flex: 1
scrollEnabled
stickySectionHeadersEnabled
sections={this.sections}
keyExtractor={item => item["#id"]}
removeClippedSubviews
renderSectionHeader={({ section }) => (
<TouchableHighlight
onPress={() => this.onSectionHeaderPressRef(section.index)}
activeOpacity={0.65}
underlayColor="rgba(0, 0, 0, 0.2)"
style={styles.sectionHeader}
>
<View style={styles.categoryContentContainer}>
<View style={styles.firstPartContent}>
<Text style={styles.categoryHeaderText}>
{section.title === "Autres"
? "Mes produits"
: section.title}{" "}
</Text>
{section.nbItems - section.nbItemsSelected === 0 ? (
<CheckBox
label=""
checked
checkboxStyle={styles.checkbox}
checkboxContainer={styles.checkboxContainer}
/>
) : (
<Text
style={[
styles.categoryHeaderText,
{ color: Colors.contrastColor },
]}
>
({section.nbItems - section.nbItemsSelected})
</Text>
)}
</View>
<Image
source={require("../../../assets/common/chevron.png")}
style={
section.index === this.state.currentCategoryOpen
? styles.categoryChevronOpen
: styles.categoryChevronClosed
}
/>
</View>
</TouchableHighlight>
)}
renderItem={({ item }) =>
this.state.currentCategoryOpen === item.categoryIndex ? (
<ShoppingListProduct
key={item["#id"]}
ingredient={item}
updateIngredient={this.updateIngredientListRef}
onLongPress={this.itemLongPressedRef}
/>
) : null}
/>
</View>
A GIF of the actual behavior ( I'm trying to scroll everytime the cursor is moving ) where we can see that the scroll only triggers when I am above a certain height.
GIF
Any help would be appreciated as I don't know if that's a bug and/or me implementing the component wrong.
Thank you by advance.
someone asked me the solution for this via email so I might as well add it here, from what i remember it was a position/imbrication problem with the components.
I can't remember exactly but I ended up with this code ( my page content changes so that's why it is set as a variable )
// render method
component = ( <SectionList
style={styles.openSectionList} // flex: 1, height: "100%"
scrollEnabled
stickySectionHeadersEnabled
sections={this.sections}
bounces={false}
keyExtractor={item =>
item["#id"] === undefined ? item.userIngredient : item["#id"]
}
getItemLayout={this.getItemLayout}
renderSectionHeader={this.renderSectionListHeaderRef}
renderItem={this.renderSectionListItemRef}
/> )
return (
<View style={{ flex: 1 }}>
{component}
</View>
)
So yeah watch out where your SectionList is defined and how many parents it has, I think it required only one
Hope this helps.
I was able to fix mine by adding this prop to the section list
stickySectionHeadersEnabled={false}
I added a marginBottom to the SectionList of equal amount of space consumed by the View on top to equalise the area.

How to get height of ScrollView with a lot of child elements?

Is there any way to get height of whole ScrollView element in React Native?
return (
<View ref='container' style={[ styles.container, backgroundColor, {width: this.props.width} ]}>
<ScrollView ref='scroll' style={styles.scrollView}> --> what height with inner content?
{this._getTitle()}
<View style={styles.content}>
{items}
</View>
<View style={[styles.empty]} />
</ScrollView>
</View>
)
I don't know if this is an officially documented API, but getting the content size can be done using the native scroll-view manager.
Add the necessary imports:
import ReactNative, {NativeModules} from 'react-native';
const ScrollViewManager = NativeModules.ScrollViewManager;
Call this in your code at a point where you already have access to the scrollview ref:
if(ScrollViewManager && ScrollViewManager.getContentSize) {
ScrollViewManager.getContentSize(ReactNative.findNodeHandle(this.scrollViewRef), (contentSize) => {
console.log(contentSize);
})
}

React Native : TabBarIOS and Navigation

I have simple app, with 3 tabs. Tabs are defined by TabBarIOS in index.ios. I’m not using Navigator nor NavigatorIOS. In each TabBarItem , I just put the component name in tags. Like this :
return(
<TabBarIOS
selectedTab={this.state.selectedTab}
//unselectedTintColor="yellow"
//tintColor="white"
//barTintColor="darkslateblue"
>
<TabBarIOS.Item
icon={{uri: 'courses.png', scale: 5}}
title="Courses"
badge={undefined}
selected={this.state.selectedTab === 'courses'}
onPress={() => {
this.setState({
selectedTab: 'courses',
});
}}>
<Courses />
</TabBarIOS.Item>
<TabBarIOS.Item
icon={{uri: 'register.png', scale: 5}}
title="Register"
badge={undefined}
selected={this.state.selectedTab === 'register'}
onPress={() => {
this.setState({
selectedTab: 'register',
});
}}>
<NavigatorIOS
//style={styles.nav}
initialRoute={{
title : 'Register',
component: Register
}}
/>
</TabBarIOS.Item>
<TabBarIOS.Item
icon={{uri: 'profile.png', scale: 5}}
title="Profile"
badge={undefined}
selected={this.state.selectedTab === 'profile'}
onPress={() => {
this.setState({
selectedTab: 'profile',
});
}}>
<Profile />
</TabBarIOS.Item>
</TabBarIOS>
);
If you see in code, in first and third tab, i'm showing content of the item by puting component name in tags like
<Courses />
But for second item, i tried using navigatorios to show component, but it shows only a blank page with title. it doesn't show the content of component. i see lots of examples working like that, but it didn't work for me. maybe because i'm not using navigator or navigaatorios for index.ios , because in most examples i see, they put navigatorios for index and set initialroute. i tried it, but didn't work for me.
Everything works fine till here. In Courses page, I have a list view with items under it (actually items with header, which are collapsible) , when user clicks on each item , I need to redirect user to a page to show that course’s details. (I should pass some arguments also).
render(){
return (
<View style={{
flex: 1
}}>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
style={styles.listView}
/>
</View>
);
}
renderRow(data) {
var header = (
<View>
<View style={styles.rowContainer}>
<View style={styles.textContainer}>
<Text style={styles.title}>{data.nid}</Text>
<Text style={styles.description} numberOfLines={0}>{data.title}</Text>
</View>
</View>
<View style={styles.separator}></View>
</View>
);
///////////
var cid = [];
var content = [];
for(let x=0; x < Object.keys(data.course).length; x++){
cid[x] = data.course[x].course_id;
content.push(
<TouchableHighlight
underlayColor='#e3e0d7'
key={x}
onPress={()=> {
this.rowPress(x); ///// here i need to redirect user to another page to show course's details
}}
style={styles.child}
>
<Text style={styles.child}>
{data.course[x].title}
</Text>
</TouchableHighlight>
);
}
var clist = (
<View style={styles.rowContainer}>
{content}
</View>
);
////////////
return (
<Accordion
header={header}
content={clist}
easing="easeOutCubic"
/>
);
}
I want to redirect user to a page and show details, and i want to have a header title and a back button (like Navigator or NavigatorIOS).
I've found a sample app that is doing exactly what i'm looking for, but it's too complicated for me, that i didn't understand how it is working,
react native tabbar-navigator (iOS)
I've looked into many examples and tutorials. i tried to implement their code into mine but it didn't work.
Also find some other tutorials using redux, but it's so complicated and hard for me. i'm looking for something more simpler.
Navigation using Redux
Looking forward to hearing from you,
Any help is highly appreciated. Thanks in Advance!
I found out that when i have few scenes and i want to navigate between them , best practice is to use Navigator or NavigatorIOS.
I continue my app and did few more scenes and components ( with few levels going deep ) and i found out that Navigator or NavigatorIOS is not working properly for that purpose. Then i switched to NavigationExperimental and that was awesome. Then i had some problems in state management, i found out about redux. it was not easy at first, but when i start it, you will love it.
So for newbies like me, it's better to start with redux at first. that would make life much easier for you :)

Categories