React Native app - NativeBase DeckSwiper not re rendering immediately when dataSource changes - react-native

I am using Picker and DeckSwiper from NativeBase, when I select a different topic from the Picker menu, it updates the state that is read by dataSource on the DeckSwiper component, which should re render to show the new content. It currently only re renders if the first card is swiped. How can I get it re render as soon as the state has changed? Here is a GIF to show how it's currently working.
Here is the code
const Item = Picker.Item;
const topics = [
{ label: "topic 1", value: "1" },
{ label: "topic 2", value: "2" },
{ label: "topic 3", value: "3" }
];
const cards = [
{ text: "Card A", topicId: "1", name: "One" },
{ text: "Card B", topicId: "2", name: "Two" },
{ text: "Card C", topicId: "3", name: "Three" },
{ text: "Card D", topicId: "1", name: "Four" },
{ text: "Card E", topicId: "2", name: "Five" },
{ text: "Card F", topicId: "3", name: "Six" }
];
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
selected: "1",
topics: topics,
cards: cards
};
}
onValueChange(value: string) {
this.setState({
selected: value,
cards: cards.filter(item => item.topicId === value)
});
}
render() {
return (
<Container>
<Header />
<Content>
<Form>
<Picker
iosHeader="Select one"
mode="dropdown"
selectedValue={this.state.selected}
onValueChange={this.onValueChange.bind(this)}
>
{this.state.topics.map((topic, i) => {
return <Item label={topic.label} value={topic.value} key={i} />;
})}
</Picker>
</Form>
<View>
<DeckSwiper
ref={c => (this._deckSwiper = c)}
dataSource={this.state.cards}
renderItem={item => (
<Card style={{ elevation: 3 }}>
<CardItem>
<Left>
<Body>
<Text>{item.text}</Text>
<Text>Topic{item.topicId}</Text>
</Body>
</Left>
</CardItem>
<CardItem cardBody>
<Image
style={{ height: 300, flex: 1 }}
source={{
uri:
"http://www.pixedelic.com/themes/geode/demo/wp-content/uploads/sites/4/2014/04/placeholder4.png"
}}
/>
</CardItem>
</Card>
)}
/>
</View>
</Content>
<View style={{ flexDirection: "row", flex: 1, position: "absolute", bottom: 50, left: 0, right: 0, justifyContent: 'space-between', padding: 15 }}>
<Button iconLeft onPress={() => this._deckSwiper._root.swipeLeft()}>
<Text>Swipe Left</Text>
</Button>
<Button iconRight onPress={() => this._deckSwiper._root.swipeRight()}>
<Text>Swipe Right</Text>
</Button>
</View>
</Container>
);
}
}

Related

FlatList not showing its data React Native

Hi guys I am trying to display data from an object to my flatlist here it is
import {ItemLists} from '../data/ItemLists';
const ListItem = ({item}) => {
return (
<View style={{margin: 10}}>
<Image source={{
uri: item.uri,
}}
style={{width:200,height:200}}
resizeMode="cover"
/>
<Text style={{margin:5}}>{item.text}</Text>
</View>
)
};
and here's my dummy data
export const ItemLists = [
{
title: 'Hot Deals',
data: [
{
"key": 1,
"text": "Title of Food",
"uri": "../../Assets/Images/featured-restau-01"
},
{
"key": 2,
"text": "Title of Food",
"uri": "../../Assets/Images/featured-restau-02"
},
{
"key": 3,
"text": "Title of Food",
"uri": "../../Assets/Images/featured-restau-03"
},
{
"key": 4,
"text": "Title of Food",
"uri": "../../Assets/Images/featured-restau-04"
},
{
"key": 5,
"text": "Title of Food",
"uri": "../../Assets/Images/featured-restau-05"
},
{
"key": 6,
"text": "Title of Food",
"uri": "../../Assets/Images/featured-restau-06"
},
{
"key": 7,
"text": "Title of Food",
"uri": "../../Assets/Images/featured-restau-07"
}
]
}
];
Now here's how I use my FlatLis
<ScrollView>
//... other codes
//... other codes
<View style={styles.HotDealsContainer}>
<View style={styles.HotDealItemContainer}>
<Text style={styles.HotDealTitle}>Hot Deals</Text>
<View style={styles.HotDealsItem}>
<FlatList
horizontal
data={ItemLists}
keyExtractor={(item) => item.key}
renderItem={({item}) => <ListItem item {...item}/>}
/>
</View>
</View>
</View>
</ScrollView>
HotDealsContainer:{
width:'100%',
height:200,
backgroundColor: 'green',
},
HotDealItemContainer:{
marginTop: -135,
marginLeft: 20,
width:Dimensions.get('window').width / 2 * 2 - 40,
height:150,
backgroundColor: 'blue',
},
HotDealsItem:{
flex:1,
justifyContent:'space-between',
flexDirection:'row',
},
HotDealTitle:{
color:'#000',
fontSize:18,
fontWeight: 'bold',
},
The current problem I am facing right now is that it won't display a single thing on the screen . Can someone point out what I am doing wrong ?
Your ItemLists has only one item which has title and data array. If you want to render that data you have to pass only that array:
<FlatList
horizontal
data={ItemLists[0].data}
keyExtractor={(item) => item.key}
renderItem={({item}) => <ListItem item {...item}/>}
/>
The second problem I noticed is that you don't pass the item property to . What you want to do is next:
<ListItem item={item} />
It will be better for readability purpose to store that array of data in a separate variable rather than in an object which is in another array

React Native Component NOT re-rendering

for some reason the component is not Re-Rendering on the setDependent, i have added the setPerson and the console does log the item without that one deleted, but is not updating the component. please see code below, as of right now is loading with no problem from the server but at the moment of deletion it does send the command to delete but the list does not get re-render, the "person" still listed on the FlatList
const RemoveDependent = ({ onPress }) =>
(
<TouchableWithoutFeedback onPress={onPress}>
<View style={{
backgroundColor: colors.dangerLight,
//height: 70,
width: 70,
//borderRadius: 35,
right:-5,
justifyContent: 'center',
alignItems: 'center'
}}>
<MaterialCommunityIcons name="trash-can" size={30} style={{ color: colors.white }} />
</View>
</TouchableWithoutFeedback>
)
function FamilyScreen(props) {
const [person, setDependent] = useState(dependents);
const handleRemove = onDependent => {
console.log(person.filter(d => d.id !== onDependent.id));
setDependent(person.filter((d) => d.id !== onDependent.id));
}
return (
<View style={{ backgroundColor: colors.white, flex: 1 }}>
<Image
source={require('../assets/familyBg.jpeg')}
style={styles.image}
resizeMode="cover"
/>
<View style={styles.details}>
<RevText style={styles.title}>Family Plan</RevText>
<RevText style={styles.description}>Description here</RevText>
</View>
<FlatList
data={dependents}
keyExtractor={personal => personal.id.toString()}
renderItem={({ item }) => (
<ListItem
onPress={() => handleRemove(item) }
title={item.name}
subTitle={item.type}
image={item.image}
renderRightActions={() => (<RemoveDependent onPress={() => handleRemove(item)} />) }
ItemSeparatorComponent={() => (<View style={{ width: '96%', left: 5, borderBottomColor: 'red', borderBottomWidth: 1 }} />)}
/>
)}
/>
</View>
);
}
Object {
"id": 1014,//REMOVED ID WHEN CLICKED
"image": 19,
"name": "Person 1",
"type": "Child",
}
Array [ //NEW ARRAY
Object {
"id": 1015,
"image": 19,
"name": "PERSON 2",
"type": "Child",
},
Object {
"id": 1016,
"image": 19,
"name": "PERSON 3",
"type": "Child",
},
Object {
"id": 1017,
"image": 19,
"name": "PERSON 4",
"type": "Child",
},
]
The main problem with this code is that your are altering a state object directly. You should treat all state objects as if they are immutable.
change
setDependent(person.filter((d) => d.id !== onDependent.id));
with
setDependent([...person.filter((d) => d.id != onDependent.id)]);

How to make a two column grid on react native?

I am tasked right now with making a screen that gives options in a grid of two columns with multiple cards as the items of a list. (You can see here)
I was trying to create a row flexbox, but it ended up simply continuing horizontally forever.
I'd like to know what would be a good way to get this effect os two columns expanding downwards.
You should use FlatList and set numColumns prop to "2" to show FlatList as grid
Here is complete code sample
import React from "react";
import { SafeAreaView, FlatList, Text, View, Image } from "react-native";
const DATA = [
{
id: "1",
title: "RUSTY DRIVE",
image:
"https://res.cloudinary.com/demo/image/upload/w_260,h_200,c_crop,g_north/sample.jpg"
},
{
id: "2",
title: "SABOR MORENO",
image:
"https://res.cloudinary.com/demo/image/upload/w_260,h_200,c_crop,g_north/sample.jpg"
},
{
id: "3",
title: "0 MESTRE PUB",
image:
"https://res.cloudinary.com/demo/image/upload/w_260,h_200,c_crop,g_north/sample.jpg"
},
{
id: "4",
title: "GRILL 54 CHEF",
image:
"https://res.cloudinary.com/demo/image/upload/w_260,h_200,c_crop,g_north/sample.jpg"
},
{
id: "5",
title: "RUSTY DRIVE",
image:
"https://res.cloudinary.com/demo/image/upload/w_260,h_200,c_crop,g_north/sample.jpg"
},
{
id: "6",
title: "SABOR MORENO",
image:
"https://res.cloudinary.com/demo/image/upload/w_260,h_200,c_crop,g_north/sample.jpg"
},
{
id: "7",
title: "0 MESTRE PUB",
image:
"https://res.cloudinary.com/demo/image/upload/w_260,h_200,c_crop,g_north/sample.jpg"
},
{
id: "8",
title: "GRILL 54 CHEF",
image:
"https://res.cloudinary.com/demo/image/upload/w_260,h_200,c_crop,g_north/sample.jpg"
}
];
export default class App extends React.Component {
_renderItem = ({ item }) => (
<View style={{ flex: 1, marginHorizontal: 20, marginBottom: 20 }}>
<Image
style={{ width: "100%", height: 140 }}
source={{ uri: item.image }}
/>
<Text style={{ textAlign: "center", marginTop: 8 }}>{item.title}</Text>
</View>
);
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<FlatList
data={DATA}
renderItem={this._renderItem}
keyExtractor={item => item.id}
numColumns={2}
style={{ flex: 1 }}
contentContainerStyle={{ paddingVertical: 20 }}
/>
</SafeAreaView>
);
}
}
App Preview
You can achieve this by simply doing something like:
<View style={{flex:1, flexDirection:"row", maxHeight:100}}>
<View style={{flex : 1, backgroundColor:"red"}}/>
<View style={{flex : 1, backgroundColor:"yellow"}}/>
</View>
Then adding new views will let you achieve such a layout, then it's up to you deciding what and how many you want to render

React Native FlatList is not scrolling

I am developing a React Native application for Learning purposes. Now I am using FlatList in my application. But I am having a problem. My flat list is not scrolling to see all the items. It bounces back when I tried to scroll it out of screen size. I used the solutions I found online adding the flex to 1 on the root, but it is not working.
Here is my code:
class Events extends React.Component {
static navigationOptions = {
title: "Events"
};
constructor(props) {
super(props);
this.state = {
data: [
{
id: 1,
name: "Name 1"
},
{
id: 2,
name: "Name 2"
},
{
id: 3,
name: "Name 3"
},
{
id: 4,
name: "Name 4"
},
{
id: 5,
name: "Name 5"
},
{
id: 6,
name: "Name 6"
},
{
id: 7,
name: "Name 7"
},
{
id: 8,
name: "Name 8"
},
{
id: 9,
name: "Name 9"
},
{
id: 10,
name: "Name 10"
},
{
id: 11,
name: "Name 11"
},
{
id: 12,
name: "Name 12"
},
{
id: 13,
name: "Name 13"
},
{
id: 14,
name: "Name 14"
},
{
id: 15,
name: "Name 15"
},
{
id: 16,
name: "Name 16"
},
{
id: 17,
name: "Name 17"
},
{
id: 18,
name: "Name 18"
},
{
id: 19,
name: "Name 19"
},
{
id: 20,
name: "Name 20"
},
{
id: 21,
name: "Name 21"
},
{
id: 22,
name: "Name 22"
},
{
id: 23,
name: "Name 23"
},
{
id: 24,
name: "Name 24"
}
]
};
}
_handleLoadMore() {}
renderItem(item) {
return (
<Card>
<CardItem>
<Left>
<Thumbnail source={{ uri: "https://www.vkguy.co.uk/images/slideshow/05.jpg" }} />
<Body>
<Text>NativeBase</Text>
<Text note>GeekyAnts</Text>
</Body>
</Left>
</CardItem>
<CardItem cardBody>
<Image
source={{ uri: "https://www.vkguy.co.uk/images/slideshow/05.jpg" }}
style={{ height: 200, width: null, flex: 1 }}
/>
</CardItem>
<CardItem>
<Left>
<Button transparent>
<Icon active name="thumbs-up" />
<Text>12 Likes</Text>
</Button>
</Left>
<Body>
<Button transparent>
<Icon active name="chatbubbles" />
<Text>4 Comments</Text>
</Button>
</Body>
<Right>
<Text>11h ago</Text>
</Right>
</CardItem>
</Card>
);
}
render() {
return (
<FlatList
contentContainerStyle={{
flex: 1,
flexDirection: "column",
height: "100%",
width: "100%"
}}
data={this.state.data}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) => this.renderItem(item)}
onEndReached={this._handleLoadMore}
/>
);
}
}
export default Events;
But it is not scrolling to see the items off the screen. How can I fix it?
Here is the screenshot. I cannot scroll down more than that.
Change some styling in FlatList view and add View as main container
render() {
return (
<View style={{ flex: 1, width: '100%' }}>
<FlatList
data={this.state.data}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) => this.renderItem(item)}
onEndReached={this._handleLoadMore}
/>
</View>
);
}
Try with
<FlatList
contentContainerStyle={{ flexGrow: 1, paddingBottom: 5 }}
data={this.state.data}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) => this.renderItem(item)}
onEndReached={this._handleLoadMore}
onEndReachedThreshold={0.5}
/>

React Native Flatlist can't see the bottom of the flatlist

I want to show a flatlist but I have a problem. In the bottom of the phone, I can't show the integrality of the post and don't scroll to it. I don't know why. Some issues ? I have try some spacing stuff with style but that's don't work like I want.
import React, { Component } from 'react'
import { View, Text, FlatList } from 'react-native'
import BlockPhoto from '../ui/BlockPhoto';
import { isTemplateElement } from '#babel/types';
interface Props { }
interface State { monTabPost: Array<TabPost> }
interface TabPost { id: number, title: string, }
const monTabPost: Array<TabPost> = [
{ id: 1, title: "Chat 1", },
{ id: 2, title: "Chat 2", },
{ id: 3, title: "Chat 3", },
{ id: 4, title: "Chat 4", },
{ id: 5, title: "Chat 5", },
{ id: 6, title: "Chat 6", },
{ id: 7, title: "Chat 7", },
{ id: 8, title: "Chat 8", },
]
export default class VueFlatList extends Component<Props, State> {
state = {
monTabPost: monTabPost ? monTabPost : []
}
render = () => {
return (
<View style={{ paddingHorizontal: 30 }}>
<Text style={{ paddingVertical: 20, backgroundColor: "black", marginBottom: 5, color: "white", textTransform: "uppercase", textAlign: "center", fontWeight: "bold" }}>Mon titre</Text>
<FlatList
//inverted
data={this.state.monTabPost}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) =>
<View>
<Text>Mon post</Text>
<BlockPhoto title={item.title} />
</View>
}
/>
</View>
)
}
}
Add contentContainerStyle={{ paddingBottom: 100 // <-- you can calibrate this }} on Flatlist component.
can replace your render to below it will work,
render = () => {
return (
<View style={{ paddingHorizontal: 30, flex: 1, width: '100%' }}>
<Text style={{ paddingVertical: 20, backgroundColor: "black", marginBottom: 5, color: "white", textTransform: "uppercase", textAlign: "center", fontWeight: "bold" }}>Mon titre</Text>
<FlatList
data={this.state.monTabPost}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) =>
<View>
<Text>Mon post</Text>
<BlockPhoto title={item.title} />
</View>
}
/>
</View>
)
}
you have to add some styling in main container view, flex occupy the entire lists of data.
I tried using paddingBottom, but it didnt work for me.
Try adding marginBottom: 150 on the Flatlist component's style.