React Native Component NOT re-rendering - react-native

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)]);

Related

Access one data from every list in react native listitem

I want to select one item from each ListItem. But the problem is that I can only choose one item at a time. I have used multiselect, but the problem is there is that multiple items could be selected from each section item.
**
I want to access one data from every list in react native listitem.I
want to select one item from each ListItem. But the problem is that I
can only choose one item at a time. I have used multiselect, but the
problem is there is that multiple items could be selected from each
section item.I have used flatlist then in renderitem I have used
listItem.
**
ProductAttributes:Object {
"Id": 9,
"Name": "Size",
"Values": Array [
Object {
"ColorSquaresRgb": null,
"CustomProperties": Object {},
"FullSizePictureUrl": null,
"Id": 21,
"IsPreSelected": false,
"Name": "8",
"PictureId": 0,
"PictureUrl": null,
"PriceAdjustment": null,
"PriceAdjustmentValue": 0,
},
Object {
"ColorSquaresRgb": null,
"CustomProperties": Object {},
"FullSizePictureUrl": null,
"Id": 22,
"IsPreSelected": false,
"Name": "9",
"PictureId": 0,
"PictureUrl": null,
"PriceAdjustment": null,
"PriceAdjustmentValue": 0,
},
],
}
ProductAttributes: Object {
"Id": 10,
"Name": "Color",
"Values": Array [
Object {
"ColorSquaresRgb": "#663030",
"CustomProperties": Object {},
"FullSizePictureUrl": "img1",
"Id": 25,
"IsPreSelected": true,
"Name": "Red",
"PictureId": 53,
"PictureUrl": "img2",
"PriceAdjustment": null,
"PriceAdjustmentValue": 0,
},
Object {
"ColorSquaresRgb": "#363656",
"CustomProperties": Object {},
"FullSizePictureUrl": "img3",
"Id": 26,
"IsPreSelected": false,
"Name": "Blue",
"PictureId": 54,
"PictureUrl": "img4",
"PriceAdjustment": null,
"PriceAdjustmentValue": 0,
},
],
}
And the UI is
<FlatList
data={this.state.product_attributes2}
ListHeaderComponent={null}
renderItem={({ item, index }) => {
console.log("ProductAttributes: ", item);
return (
<>
<ListItem.Accordion
style={{ height: 50 }}
content={
<>
<Iconsss
name="filter-menu"
size={20}
style={{ marginRight: 10 }}
/>
<ListItem.Content>
<ListItem.Title>{item.Name}</ListItem.Title>
</ListItem.Content>
</>
}
isExpanded={this.state.expanded}
onPress={() => {
this.setState({ expanded: !this.state.expanded });
}}
>
<View
style={{
borderTopWidth: 1,
borderColor: "rgba(38, 38, 38,0.8)",
}}
>
{item?.Values?.map((l, i) => {
return (
<ListItem
key={i}
onPress={() => {
console.log(l.IsPreSelected);
this.setState({
select_choice: true,
choice_name: l.Name,
// IsPreSelected:l.IsPreSelected,
});
}}
bottomDivider
Checkbox
>
<ListItem.CheckBox
// checked={this.state.IsPreSelected}
checked={l.IsPreSelected === true ? true : false}
onPress={() =>
this.setState({ IsPreSelected: !l.IsPreSelected })
}
/>
<ListItem.Content>
<ListItem.Title
style={{ color: "rgba(38, 38, 38,1)" }}
>
{l.Name}
</ListItem.Title>
</ListItem.Content>
{l?.ColorSquaresRgb === null ? null : (
<View
style={{
backgroundColor: l?.ColorSquaresRgb,
height: 20,
// width:20,
borderRadius: 20,
flex: 0.3,
justifyContent: "center",
// alignItems:"center",
}}
/>
)}
{l?.PictureUrl === null ? null : (
<Image
source={{ uri: l.PictureUrl }}
style={{
flex: 0.7,
resizeMode: "contain",
height: 50,
}}
/>
)}
</ListItem>
);
})}
</View>
</ListItem.Accordion>
</>
);
}}
keyExtractor={(item, index) => {
return index.toString();
}}
ListFooterComponent={null}
/>

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

select one item from flatlist

I created this list of items and I want to let user select one item and then change style of this item.
this is my approach:
class Gift extends React.Component {
constructor(props){
super(props)
this.titleUpValue = new Animated.Value(0);
this.state = {
isLoading: false,
listGifts: [
{
"id" : "1",
"type" : 'gift' ,
"etat" : 1,
"titreTransaction": "عدد الوحدات",
"contenuTrans": "400",
"dateTrans": "2019-07-31 17:47:31"
},
{
"id" : "2",
"type" : 'ba' ,
"etat" : 1,
"titreTransaction": "عدد الوحدات",
"contenuTrans": "1000",
"dateTrans": "2019-07-31 17:42:57"
},
{
"id" : "3",
"type" : 'ba' ,
"etat" : 1,
"titreTransaction": "عدد الوحدات",
"contenuTrans": "500",
"dateTrans": "2019-07-31 17:31:35"
},
}
],
itemId: null,
btnDisabled: true,
itemindex: null,
}
}
PressedItem = (itemId) => {
this.setState({ itemId: itemId, btnDisabled: false,})
}
renderItem = ({ item }) => {
return (
<TouchableOpacity
onPress={() => { this.setState({ itemindex: item.id, itemId: item.id, btnDisabled: !this.state.btnDisabled, }), console.warn('id > ' + this.state.btnDisabled) }}
style= {[
StylesGift.giftItem,
this.state.itemindex === item.id ? StylesGift.SelectedlistItem : StylesGift.UnselectedlistItem
]}>
<Image source={Images.gift1}
style={StylesGift.imageStyle}
resizeMode={'contain'}
/>
<View style= {StylesGift.footGift}>
<View style= {StylesGift.nameGiftContainer}>
<View style= {StylesGift.valueGiftContainer}>
<Text style= {StylesGift.valueGiftText}>200</Text>
</View>
<Text style= {StylesGift.nameGiftText}>الهدايا</Text>
<Text style= {StylesGift.nameGiftText}>{item.id}</Text>
</View>
</View>
<View style= {StylesGift.headGift}>
<View style= {StylesGift.icGiftContainer}>
<IconFA name="check" size={hp('1.6%')} color= {Colors.white} style={StylesGift.icGift}/>
</View>
</View>
</TouchableOpacity>
)
}
render() {
return (
<View style={Styles.listContainer}>
{
this.state.isLoading ?
<ActivityIndicator size='large' style={Styles.styleAI} color={Colors.mainYellow}/>
:
<FlatList
style={Styles.flatlist}
contentContainerStyle={Styles.flatContent}
data={this.state.listGifts}
keyExtractor={(item) => item.id.toString()}
renderItem={this.renderItem}
numColumns={2}
/>
}
</View>
);
}
}
export default Gift;
I dont use the PressedItem function for test, the consol.warn() in onPress show the last state not the current state.
for exemple when I click on the item with id = "1" it show me id > null when I click on the item with id = "2" then it show me id > 1... and the style deosn't change even with this condition:
this.state.itemindex === item.id ? StylesGift.SelectedlistItem : StylesGift.UnselectedlistItem
this is the 3 main Styles:
giftItem: {
width: wp('42%'),
height: hp('30%'),
alignItems: 'center',
backgroundColor: Colors.white,
borderRadius: wp('2%'),
overflow: 'hidden',
marginVertical: wp('2%'),
marginHorizontal: wp('2%'),
// borderWidth: 1, borderColor: 'blue',
},
UnselectedlistItem: {
elevation: 2,
borderWidth: 1, borderColor: 'red',
},
SelectedlistItem: {
elevation: 8,
borderWidth: 1, borderColor: 'blue',
},
I think my approach is logic and most work but I don't know what's wrong, states: itemindex and itemId doesn't change in setState
It's okey, I just had to add extraData={this.state} as parameter in flatlist for telling the flatlist to re-render
<FlatList
style={Styles.flatlist}
contentContainerStyle={Styles.flatContent}
data={this.state.listGifts}
keyExtractor={(item) => item.id.toString()}
renderItem={this.renderItem}
numColumns={2}
extraData={this.state}
/>

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.

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

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>
);
}
}