Mapping view not updating on tab navigator in react-native - react-native

I have 4 tabs load using tabnavigator. I have home, favourite, cart and profile screen. User will choose desired product on home, add it to cart. The badge count on tab is updating, but when I'm go to cart screen, it is still plain empty.
I'm running on development. So if I refresh my script on VSCode, the product will be show on cart screen.
This is my cart script:-
renderProductList() {
var contents = appGlobal.ObjProduct.map((item) => {
return (
<Content key={item.ProdID}>
<TouchableOpacity onPress={() => {
console.log('Touch item: ' + JSON.stringify(item));
}}>
<Card>
<CardItem>
<Left>
<FastImage
source={{ uri: item.ProdImage, priority: FastImage.priority.normal, }}
style={{
width: 50,
height: 50,
alignItems: 'center',
justifyContent: 'center',
}}
resizeMode={FastImage.resizeMode.cover}
/>
</Left>
<Body>
<Text>{item.ProdName}</Text>
</Body>
<Right>
</Right>
</CardItem>
</Card>
</TouchableOpacity>
</Content>
);
});
return (
<Content padder>
{contents}
</Content>
)
}
renderNoProduct() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', }}>
<SvgUri width="150" height="150" source={EmptyCart} />
<Text style={{ color: 'gray', marginTop: 10 }}>Your cart is empty :(</Text>
</View>
)
}
render() {
return (
<Container>
<Header searchBar rounded>
<Left style={{ flex: null }}>
</Left>
<Body style={{ flex: 3 }}>
<Title style={{ marginLeft: 10, }}>Shopping Cart</Title>
</Body>
<Right style={{ flex: null }}>
</Right>
</Header>
{appGlobal.ObjProduct.length > 0 ? this.renderProductList() : this.renderNoProduct()}
<Footer>
<FooterTab>
<Button style={{ backgroundColor: '#d15f02' }}>
<Text style={{ color: 'white' }}>Proceed to order</Text>
</Button>
</FooterTab>
</Footer>
</Container>
);
}
It is another way to make it global mapping or product change when using tab navigator?

You need to call a function when the focused screen changes on TabNavigation
on your Cart tab use this:
import { withNavigationFocus } from 'react-navigation';
class CartScreen extends React.Component {
componentDidUpdate(prevProps) {
if (prevProps.isFocused !== this.props.isFocused) {
// Call any action to update you view
//fetch data when the component is focused
//To prevent extra component re-renders, you may need to write some logic in shouldComponentUpdate
}
}
render() {
return (
<Container>
<Text>{this.props.isFocused ? 'Focused' : 'Not focused'}</Text>
</Container>
);
}
}
// withNavigationFocus returns a component that wraps CartScreen and passes
// in the navigation prop
export default withNavigationFocus(CartScreen);
withNavigationFocus
withNavigationFocus is a higher-order component which passes the isFocused prop into a wrapped component. It's useful if you need to use the focus state in the render function of your screen component or another component rendered somewhere inside of a screen.

Related

Multiple item data. Show the data as clicked in the dynamically modal with react-native

FOOD> PIZZA> clicking on any pizza opens a modal. I want to show the information of the pizza clicked in this modal. I looked at many similar examples but I could not get out of it. So I need help. I add some parts of the code below. At the same time, the code is available in the expo and the link below
snack.expo.io/#ibrahimyolbir/e48b05
accordion
<Accordion
dataArray={this.state.menus}
animation={true}
expanded={true}
renderHeader={this._renderHeader}
renderContent={this._renderContent}
/>
my open modal button in the render content
onPress={this.triggerModal(food)}
_renderContent = (item) => {
return (
<List>
{
item.food.map((food, index) => {
return (
<ListItem style={{
backgroundColor: "#f0f0f5",
padding: 10,
marginLeft: 0,
paddingRight: 10,
fontStyle: "italic",
listStyleType: "none",
flexDirection: "row",
justifyContent: "space-between"
}}>
<TouchableOpacity
onPress={this.triggerModal(food)}
style={{
flexDirection: "row",
justifyContent: "space-between"
}}
>
<Left style={{
maxWidth: 57
}}>
<Thumbnail source={require("../assets/images/left-food-icon.png")} />
</Left>
<Body>
<Text >{food.name}</Text>
<Text note >{food.description}</Text>
</Body>
<Right>
<Text >{food.price} :-</Text>
</Right>
</TouchableOpacity>
</ListItem>
)
}
)
}
</List>
);
}
MODAL
<Modal
style={{ marginTop: 122 }}
isVisible={this.state.display}
visible={this.state.display}
onSwipeComplete={() => this.setState({ isVisible: false })}
onSwipeThreshold={1}
swipeDirection="down"
animationType="slide"
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}>
<View style={{ flex: 1, backgroundColor: "#fff" }}>
<Text>Hello!</Text>
<TouchableOpacity onPress={this.closeDisplay} style={{ marginTop: 40, marginLeft: 150 }}>
<Text> CLOSE MODAL </Text>
</TouchableOpacity>
{/* <Text> {this.state.menus} </Text> */}
</View>
</Modal>
One of the way can be:
1)Create a new state
currentChildData:[],
currentParentData:[],
2)Pass parent id and child index in onPress event
<TouchableOpacity onPress={()=>this.triggerModal(item.id,index)}
3)Using that passed index and parent id,we can extract relevant information about(to be clicked item) from menus state
triggerModal = (ParentIndex,childIndex) => {
this.setState(prevState => {
let ParentData=[...prevState.menus].find(each=>each.id==ParentIndex)
return {
display: true,
currentChildData: ParentData.food[childIndex],
currentParentData: ParentData,
}
});
}
4)Now we have information of(to be clicked item) in our state. We then can use it like (name of item shown below) inside Modal
<Text>{this.state.currentChildData.name}</Text>
Working Code: https://snack.expo.io/By_QVbPMI
U missed the key from mapped array in a ListItem component. Add it as a prop key={Index} .
Also U need item from map as argument in ur onPress, cuz u need to push visited/selected elements to the state. {()=>this.openModal(itemFromMap)}
And then u can manipulate with data like u need.
As I can understood u have array of objects. Object.keys(itemFromMap).map(...
And return data to the needed part of ur modalInnerContainer.

Align all icon to the right of page regardless of start point React Native

I want to be able to align all reply icons to the far right, where the red line is, regardless of where they start.
Edit: added more information to show how recursion is used in the component. Why I try to use some answers that work without recursion, I receive an undesired effect.
This is the code I have in place so far:
class Comment extends Component {
render() {
return(
<View>
<Header
rounded
style={{
backgroundColor: '#ffffff',
position: 'relative',
}}
>
<View style={{flexDirection: 'row', flexWrap: 'wrap', right: '43%', top: '50%'}}>
<Icon name='chevron-left' size={10} color='#006FFF' style={{top: '6%'}}/>
<NativeText
onPress={() => this.props.history.push('/')}
style ={{color: '#006FFF', fontSize: 12, fontFamily: 'Montserrat-Regular'}}
>
Back
</NativeText>
</View>
</Header>
<View
style={{paddingLeft: '2%', paddingTop: '2%'}}
>
<CommentList
options={this.props.location.state.comments}
currentUser={this.props.location.state.currentUser}
history={this.props.history}
reportId={this.props.location.state.reportId}
optionsForBackButton={this.props.location.state.comments}
/>
</View>
</View>
)
}
}
export default withRouter(Comment)
const CommentList = ({options, currentUser, history, reportId, optionsForBackButton}) => {
return (
<View>
{options.map(option => (
<View
style={{flexDirection: 'row'}}
>
<NativeText
style={{fontSize: 12, fontFamily: 'Montserrat-Regular'}}
>
{option.content}
</NativeText>
<View
style={{flex: 1, alignItems: 'flex-end' }}
>
<Icon
name='reply'
size={12}
// onPress={() => {
// setModalVisible(true)
// changeParentId(option._id)
// }}
onPress={() => history.push({pathname: '/create-comment', state: {content: option.content, currentUser: currentUser, reportId: reportId, parentCommentId: option._id, optionsForBackButton: optionsForBackButton}})}
/>
</View>
{
<View
style={{left: '10%'}}
>
<CommentList
options={option.reply}
optionsForBackButton={optionsForBackButton}
history={history}
currentUser={currentUser}
reportId={reportId}
/>
</View>
}
</View>
))}
</View>
)
}
Set your icon containing view's flex value to 1. This should cause it to fill all remaining space.
See the following snack: https://snack.expo.io/#jrdndncn/playful-churros
class Comment extends React.Component {
render() {
return (
<View
style={{
marginVertical: 2,
flexDirection: 'row',
marginLeft: (this.props.indent || 0) * 20,
}}>
<Text>{this.props.text}</Text>
<View style={{ flex: 1, alignItems: 'flex-end' }}>
<View style={{ width: 20, height: 20, backgroundColor: 'red' }} />
</View>
</View>
);
}
}
<Comment text="hello" indent={0} />
<Comment text="hello" indent={1} />
<Comment text="hello" indent={2} />
Basically marginLeft:'auto' will do the trick. just add style to icon as :
<Icon
name='reply'
size={12}
style={{marginLeft:'auto'}}
// onPress={() => {
// setModalVisible(true)
// changeParentId(option._id)
// }}
onPress={() => history.push({pathname: '/create-comment', state: {content: option.content, currentUser: currentUser, reportId: reportId, parentCommentId: option._id, optionsForBackButton: optionsForBackButton}})}
/>
i added marginLeft:'auto' in style it will automatically shown at the right end of the screen.

React Native and native base edit data page

I'm trying to create a page that where I can edit the 'tenant' data.
Here is my page:
import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';
import {
Container, Header, Content, Card,
CardItem, Text, Icon, Right,
Left, Body, Title, Button }
from 'native-base';
import { Avatar } from 'react-native-elements';
import NavigationService from '../NavigationService';
class TenantDetails extends Component {
render() {
const { navigation } = this.props;
return (
<Container>
<Header>
<Left>
<Button
transparent
onPress={() => NavigationService.navigate('Tenants')}
>
<Icon name='arrow-back' />
</Button>
</Left>
<Body>
<Title>My Name</Title>
</Body>
<Right />
</Header>
<Content>
<View style={styles.userRow}>
<View style={styles.userImage}>
<Avatar
rounded
size="large"
source={{
uri: 'https://myirent.com/rent/appImg/person-icon.png',
}}
/>
</View>
<View>
<Text style={{ fontSize: 16 }}>Jonh Test</Text>
<Text
style={{
color: 'gray',
fontSize: 16,
}}
>
joinh#gmail.com{'\n'}xxx-xxx-xxxx
</Text>
</View>
</View>
<Card>
<View style={styles.containerTextHeader}>
<Text style={styles.infoTextHeader}>Tenant Details</Text>
</View>
<CardItem>
<Icon active name="logo-googleplus" />
<Text>First Name</Text>
<Right>
<Icon name="arrow-forward" />
</Right>
</CardItem>
</Card>
</Content>
</Container>
);
}
}
const styles = StyleSheet.create({
scroll: {
backgroundColor: 'white',
},
userRow: {
alignItems: 'center',
flexDirection: 'row',
paddingBottom: 8,
paddingLeft: 15,
paddingRight: 15,
paddingTop: 6,
},
userImage: {
marginRight: 12,
},
listItemContainer: {
height: 55,
borderWidth: 0.5,
borderColor: '#ECECEC',
},
containerTextHeader: {
paddingTop: 20,
paddingBottom: 12,
backgroundColor: '#F4F5F4',
},
infoTextHeader: {
fontSize: 16,
marginLeft: 20,
color: 'gray',
fontWeight: '500',
},
});
export default TenantDetails;
Thanks. I 'm having issue with the right arrow not align to the right (image below). Also, how can I change the to have a label and value (Where I have First Name)? So when I click on it, I can open. modal to edit the value
Screen:
here is part of your code. i add Left tag:
<Card>
<View style={styles.containerTextHeader}>
<Text style={styles.infoTextHeader}>Tenant Details</Text>
</View>
<CardItem>
<Left>
<Icon active name="logo-googleplus" />
<Text>First Name</Text>
</Left>
<Right>
<Icon name="arrow-forward" />
</Right>
</CardItem>
</Card>
for modal problem, you can install react-native-modal by npm install --save react-native-modal.
wrap a button around CardItem that you need to onPress it. then call on onPress, a method that it changes your state of visibility for modal.
something such as this code:
<Modal
style={{ margin: 0 }}
isVisible={this.state.modalVisible}
/>
for changing of your field such as name, etc, use state of component

Components Render then Disappear

I have a relatively simple component which renders properly on iOS but not Android. The component appears to render then the top 1/2 of the screen fades away. I'm sure the component is rendered but it appears the subcomponents are fading out or being covered by something. Given that the animation which occurs (quickly) looks like a fade, I think the components are still there.
The component is instantiated by a component which is created by react-navigation as a tab. This component has native-base components. The navigation.push() instantiates a react-native based component. All of the data required to render is in this.state object. Debugging reveals nothing.
Switching to another tab then back resolves the problem. Forcing re-rendering() in the event handler when the tab is focused has no effect.
I'm stumped.
This is the code:
import React, { Component } from 'react';
import {
Image,
} from 'react-native';
import {
Container,
Content,
Body,
Header,
Left,
Right,
Thumbnail,
ListItem,
List,
Text,
Button,
Footer,
FooterTab,
Card,
CardItem,
} from 'native-base';
import QRCode from 'react-native-qrcode';
export default class UnitDetailScreen extends Component {
static navigationOptions = ({ navigation }) => {
return {
title: 'Unit Details',
headerRight: <Button onPress={
() => {
navigation.navigate(
'UnitInstallation',
{ item: navigation.getParam('item') }
)
}
}>
<Text>Edit</Text>
</Button>,
}
};
state = {
};
componentDidMount() {
const navigation = this.props.navigation;
const item = navigation.getParam('item');
this.setState({ item: item, navigation: navigation });
}
getBatteryImage(item) {
return { uri: 'battery-green.png' };
}
render() {
if (this.state.item === undefined) {
return <Text>loading...</Text>;
}
// ok, now this is really wierd... the item is actually pointing to a row when this method called so we can't use getParam('item')
const rowStyle = {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-start',
marginLeft: 10,
marginRight: 10,
padding: 10,
borderBottomColor: '#888'
};
const noPhoto = { uri: 'no-photo.png' }
return <Container>
<Content>
<Card>
<CardItem>
<Left>
<Thumbnail source={noPhoto} />
<Body>
<Text>Big Bad Machine</Text>
<Text note>The Lab</Text>
</Body>
</Left>
</CardItem>
</Card>
<Card>
<CardItem bordered>
<Image style={{
flex: 1,
height: 30,
width: undefined,
resizeMode: 'contain'
}} source={this.getBatteryImage(this.state.item)} />
</CardItem>
<CardItem>
<Left><Text style={{ fontWeight: 'bold' }}>Installed</Text></Left>
<Right><Text>{this.state.item.unit.installDate}</Text></Right>
</CardItem>
<CardItem>
<Left><Text style={{ fontWeight: 'bold' }}>Model</Text></Left>
<Right><Text>The model</Text></Right>
</CardItem>
<CardItem>
<Left><Text style={{ fontWeight: 'bold' }}>Serial</Text></Left>
<Right><Text>{this.state.item.unit.serialNumber}</Text></Right>
</CardItem>
<CardItem>
<Left><Text style={{ fontWeight: 'bold' }}>Purchased</Text></Left>
<Right><Text>{this.state.item.unit.purchaseDate}</Text></Right>
</CardItem>
<CardItem>
<Left><Text style={{ fontWeight: 'bold' }}>Installation</Text></Left>
<Right>
<Thumbnail square source={noPhoto} />
</Right>
</CardItem>
<CardItem>
<Left><Text style={{ fontWeight: 'bold' }}>QR Code</Text></Left>
<QRCode
value={this.state.item.unit.id}
size={80}
/>
</CardItem>
<CardItem>
<Left><Text style={{ fontWeight: 'bold' }}>Serial</Text></Left>
<Right><Text>{this.state.item.unit.serialNumber}</Text></Right>
</CardItem>
<CardItem>
<Left><Text style={{ fontWeight: 'bold' }}>ID</Text></Left>
<Right><Text>{this.state.item.unit.id}</Text></Right>
</CardItem>
</Card>
</Content>
<Footer>
<FooterTab>
<Button bordered light>
<Text>Photos/Notes</Text>
</Button>
<Button bordered light>
<Text>Installation Media</Text>
</Button>
</FooterTab>
</Footer>
</Container>
}
}
Initial render:
Navigate away:
Navigate back:
I fixed the problem using the SVG version of the component:
npm install react-native-qrcode-svg --save
The props to supply are the same for my application. This solved the problem.

React native toolbar styling

I’m using react native base. I want to centre align the title in iOS and android both, since text is long it hides it with “…”.
I've tried different option unable to fix it. How can I fix it?
Code:
<Header iosStatusbar="light-content" androidStatusBarColor='#000' >
<Left>
<Button transparent onPress={() => this.navigateCustom("goBack")}>
<Icon name="arrow-back" />
</Button>
</Left>
<Body>
<Title>CLAP TO SUPPORT US</Title>
</Body>
<Right>
<Button transparent onPress={()=> this.navigateCustom("DrawerOpen") }>
<IconEvil name={"menu"} style={{ color: "rgb(255,255,255)", fontSize:30}}/>
</Button>
</Right>
</Header>
EDIT:
When I apply flex:1 to left right and body it changes nothing but applying flex:4 to body shows the title but it’s not centred
<Header iosStatusbar="light-content" androidStatusBarColor='#000' >
<Left style={{flex:1}}>
<Button transparent onPress={() => this.navigateCustom("goBack")}>
<Icon name="arrow-back" />
</Button>
</Left>
<Body style={{flex:4}}>
<Title>CLAP TO SUPPORT US</Title>
</Body>
<Right style={{flex:1}}>
<Button transparent onPress={()=> this.navigateCustom("DrawerOpen") }>
<IconEvil name={"menu"} style={{ color: "rgb(255,255,255)", fontSize:30}}/>
</Button>
</Right>
</Header>
Result:
Applying center alignment:
This is what i have tested on my device ios simulator, and Samsung Galaxy S7Edge and emulator.
import React, { Component } from 'react';
import { Container, Header, Left, Body, Right, Button, Icon, Title } from 'native-base';
export default class App extends Component {
render() {
return (
<Container>
<Header>
<Left style={{ flex: 1 }}>
<Button transparent>
<Icon name='arrow-back' />
</Button>
</Left>
<Body style={{ flex: 4, justifyContent: 'center', alignItems: 'center' }}>
<Title>Title Center</Title>
</Body>
<Right style={{ flex: 1 }}>
<Button transparent>
<Icon name='menu' />
</Button>
</Right>
</Header>
</Container>
);
}
}
This is what i have tested and result.
I recommend you to check your React-Native package version and compare.
Here my last version:
"native-base": "^2.3.6",
"react": "16.2.0",
"react-native": "0.52.0",
EDIT:
CODE:
import React, { Component } from 'react';
import { Container, Header, Left, Body, Right, Button, Icon, Title } from 'native-base';
export default class App extends Component {
render() {
return (
<Container>
<Header>
<Left style={{ flex: 1 }}>
<Button transparent>
<Icon name='arrow-back' />
</Button>
</Left>
<Body style={{ flex: 4, justifyContent: 'center', alignItems: 'center' }}>
<Title>Title Center</Title>
</Body>
<Right style={{ flex: 1 }}>
<Button transparent>
<Icon name='menu' />
</Button>
</Right>
</Header>
</Container>
);
}
}
NEXUS S RESULT
React Native (NativeBase) follows Android and iOS guidelines,
The title is on the Left of the header for Android and Center for iOS.
If you want it to be in the center, Please apply:
flex: 1 to <Left>, <Body> and <Right>
Example:
<Left style={{ flex: 1 }}>
</Left>
<Body style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Title>Home</Title>
</Body>
<Right style={{ flex: 1 }}>
</Right>