Click Handler immediately invoked in React Native - javascript

I've written a click handler to resolve a download button to the google play store URL.
The problem is that when the page loads, the URL is immediately visited.
The click handler is nested inside an onPress attribute, and I don't press anything, so I'm struggling to understand why this would be happening.
Any help would be appreciated!
OpenURL.js:
'use strict';
import React, {
Component,
PropTypes,
Linking,
StyleSheet,
Text,
TouchableNativeFeedback,
TouchableHighlight,
View
} from 'react-native';
class OpenURLButton extends Component {
constructor(props) {
super(props);
}
handleClick(url) {
console.log(url);
console.log('handling click! this is : ');
console.dir(this);
Linking.canOpenURL(this.props.url).then(supported => {
if (supported) {
Linking.openURL(this.props.url);
} else {
console.log('Don\'t know how to open URI: ' + this.props.url);
}
});
}
render() {
console.log('logging "this" inside render inside OpenURL.js:');
console.dir(this);
return (
<TouchableHighlight onPress={this.handleClick(this.props.appStoreUrl)}>
<Text>Download {this.props.appStoreUrl}</Text>
</TouchableHighlight>
);
}
}
OpenURLButton.propTypes = {
url: React.PropTypes.string,
}
export default OpenURLButton;
Inventory.js:
<ScrollView>
<View style={styles.ImageContainer}>
<Image style={styles.ImageBanner} source={{uri: selectedInventory.bannerImage}} />
</View>
<View style={styles.ListGridItemCaption}>
<Image style={[styles.ImageThumb, styles.ImageGridThumb]} source={{uri: selectedInventory.thumbImage}} />
<Text style={styles.Text} key="header">{name}</Text>
</View>
<View>
<Text>{selectedInventory.description}</Text>
<OpenURLButton url={selectedInventory.appStoreUrl}/>
</View>
</ScrollView>

Change:
<TouchableHighlight onPress={this.handleClick(this.props.appStoreUrl)}>
<Text>Download {this.props.appStoreUrl}</Text>
</TouchableHighlight>
To:
<TouchableHighlight onPress={() => {this.handleClick(this.props.appStoreUrl)}}>
<Text>Download {this.props.appStoreUrl}</Text>
</TouchableHighlight>
With the change you are creating anonymous function that are calling on "your" method. This will work.

Related

React Native: I am getting error while trying to get image from cloud firestore

I am getting source.uri should not be an empty string. How can i solve this?
I am using google cloud firestore to store all the images there and render it in my app, then this error shows up and i have no idea how to fix it, please help me solve this.
Here is my code:
import React from 'react';
import {
TouchableOpacity,
Image,
View,
Text
} from 'react-native';
import storage from '#react-native-firebase/storage';
import styles from '../styles/Android.style';
class Catalog extends React.Component {
constructor(props) {
super(props)
this.state = {
image : ''
}
}
retrieveImages = async () => {
const url = await storage()
.ref('/catalogs/web_hi_res_512.png')
.getDownloadURL();
this.setState({image : url})
}
componentDidMount() {
this.retrieveImages()
}
render() {
return (
<View style={styles.homeContainer}>
<TouchableOpacity style={styles.catalogItem}>
<View>
<Image
source={{uri: this.state.image}}
style={styles.catalogImage}
/>
</View>
<View style={styles.descriptionContainer}>
<Text style={styles.descriptionPrice}>Ini teks</Text>
<Text style={styles.descriptionAddress}>Ini deskripsi</Text>
</View>
</TouchableOpacity>
</View>
);
}
}
export default Catalog;
You have initialised with empty string (image : '') in your component state, so when component will load, source.uri will be initialised with '' because by that time you did not get the image from cloud firestore.
One solution can be to initialise the state with some default image and show that image in your Image component until the image from the cloud is downloaded.
As you have initialised your image state as an empty string, you are getting this error.
Conditionally rendering the image component would easily solve this. Just do:
<View style={styles.homeContainer}>
<TouchableOpacity style={styles.catalogItem}>
<View>
{image !== '' ? (
<Image
source={{uri: this.state.image}}
style={styles.catalogImage}
/>
) : null}
</View>
<View style={styles.descriptionContainer}>
<Text style={styles.descriptionPrice}>Ini teks</Text>
<Text style={styles.descriptionAddress}>Ini deskripsi</Text>
</View>
</TouchableOpacity>
</View>

How can I detect which <View> my finger is currently on?

I have a structure like this:
<View style={container}>
<View style={first}></View>
<View style={second}><View>
<View style={third}</View>
</View>
The container pretty much fills the whole screen.
When the user touches the container and moves the finger around without lifting the finger, I would like to know which View the finger is currently placed at.
Use TouchableWithoutFeedback to wrap around your views, and then you can call the onPressIn function to detect touch event.
You cannot detect the touched view unless and until you don't have any touch event on it.
To do that you can use TouchableOpacity (respond to the press and have visual feedback when touched.) or TouchableWithoutFeedback (it won't show any visual feedback when touched)
Below is the sample example as required:
import React, { Component } from 'react'
import {
TouchableOpacity,
View
} from 'react-native'
export default class SampleComponent extends Component {
constructor(props) {
super(props)
}
_onPressView = (viewName) => {
console.log("Tapped View ===> ", viewName)
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={() => this._onPressView("FirstView")}>
<View style={styles.first}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this._onPressView("SecondView")}>
<View style={styles.second}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this._onPressView("ThirdView")}>
<View style={styles.third}/>
</TouchableOpacity>
</View>
);
}
}

Single instance of component react native

I want to make a component where it renders a modal.
This component should have states{Key(integer),ImageLink(string),Visible(bool)}.
I am using flatlist. I want to render the component's modal on flatlist parent but component. States changes upon touch on flatlist child.
For example:
Modal Component which means to be single instance
import React from "react";
import {
View,
Modal,
Text,
StyleSheet,
TouchableHighlight,
Platform
} from "react-native";
export default class MySingleInstanceModal extend Component{
constructor(props) {
super(props);
this.state = {
Visiable: props.Visiable, \\Bool For turning Modal On or Off
ImageLink: props.ImageLink, \\String Image Online Link
Key: props.PostKey,\\integer Key
};
}
NextImage = (Current,Link )=> {
this.setState({ ImageLink: Link,Key:Current+1 });
};
ToggleMeOff = () => {
this.setState({ TurnMeOn: false });
};
ToggleMeOn = (MyKey,MyLink) => {
this.setState({ TurnMeOn: true,ImageLink: MyLink,Key:MyKey });
};
PrevImage = (Current,Link )=> {
this.setState({ ImageLink: Link,Key:Current-1 });
};
render() {
return (
<View>
<Modal
animationType="slide"
transparent={false}
visible={this.state.TurnMeOn}
>
<View style={{ marginTop: 22 }}>
<View>
<Text>Hello World!</Text>
<TouchableHighlight onPress={this.ToggleMeOff}>
<Text>Hide Modal</Text>
</TouchableHighlight>
<Image
source={{ uri: this.state.ImageLink }}
resizeMethod={"resize"}/>
</View>
</View>
</Modal>
</View>
);
}
}
Calling In Flatlist Parent:
render() {
return (
<View style={Style1.container}>
<MySingleInstanceModal/> // Here I want to call render
<FlatList
data={data}
initialNumToRender={4}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
onEndReached={this._reachedEnd}
refreshing={isRefreshing}
onEndReachedThreshold={0.5}
onRefresh={this._refreshdata}
ListFooterComponent={this.renderFooter}
/>
</view>)
}
And want to change states of MySingleInstanceModal in flatlist items(flatlist child)
somewhere in the rendering of flatlist child item
render(){
return (
...
<TouchableHighlight onPress={() =>
MySingleInstanceModal.ToggleMeOn(this.state.Link,this.state.Key)}>
<Text>Open Modal For Me</Text>
</TouchableHighlight>
...
)
}
Which means component will render at parent but its states will be controlled by the child(Every flatlist item)

How to move an Image on click in React Native

I've recently been learning React Native but haven't really found a way to manipulate the DOM.
I've been trying to make it so that if I click on the TouchableHighlight my Image moves down a couple of px, but I have not managed to get it to move yet and I honestly don't know how to go from here.
My onclick function works since it does return the log every time the button is clicked.
As of now I have this:
export default class MainBody extends Component {
onclick = () => {
console.log('On click works')
};
render() {
return (
<ScrollView showsHorizontalScrollIndicator={false} style={Style.horList} horizontal={true}>
<View >
{/*i need to move this Image down!*/}
<Image source={require("./img/example.png")}/>
<View>
<Text style={Style.peopleInvited}>This is text</Text>
</View>
{/*When clicked on this touchable highlight!*/}
<TouchableHighlight onPress={this.onclick}}>
<Image source={require('./img/moveImg.png')}/>
</TouchableHighlight>
</View>
</ScrollView>
}
If someone could help me get past this that would be greatly appreciated.
Thank you so much for your time!
There are many ways to do this, but perhaps the easiest way would be using states.
class MainBody extends Component {
constructor(props) {
super(props);
this.state = {
top: 0 // Initial value
};
}
onclick = () => {
console.log('On click works')
this.setState( { top: this.state.top + 5 }) // 5 is value of change.
};
render() {
return (
<ScrollView showsHorizontalScrollIndicator={false} horizontal={true}>
<View >
{/*i need to move this Image down!*/}
<Image style={{top: this.state.top}}source={require("./img/example.png")}/>
<View>
<Text>This is text</Text>
</View>
{/*When clicked on this touchable highlight!*/}
<TouchableHighlight onPress={this.onclick}>
<Image source={require("./img/moveImg.png")}/>
</TouchableHighlight>
</View>
</ScrollView>
);
}
}

Sub-Navigator for not working

I am trying to create a sub-navigation functionality in my app and want to display a list of my so called cardviews (right now ive just stored them in a ScrollView, but nevermind that), and my goal is to display the cards in such a manner so that the content in component one shows when I press one and two when I press two.
/* #flow */
'use strict';
import React, {
Component,
Navigator,
StyleSheet,
Text,
View,
ScrollView,
TouchableOpacity,
TouchableHighlight,
Image,
} from 'react-native';
import styles from '../Styles/style';
import home from '../Styles/home';
import feed from '../Styles/feed';
import {Actions} from 'react-native-router-flux';
import Icon from 'react-native-vector-icons/Ionicons';
var CardView = require('./CardView');
var colors = require('../Styles/colorscheme');
var Home = React.createClass({
getInitialState: function() {
return {
componentSelected: 'One'
}
},
changeComponent: function(component) {
this.setState({
componentSelected: component
})
},
renderComponent: function(component) {
if(component == 'One') {
return <ComponentOne changeComponent={this.changeComponent} />
} else if(component == 'Two') {
return <ComponentTwo changeComponent={this.changeComponent} />
}
},
render: function() {
return (
<View>
<View style={{flex:1}}>
<View style={styles.controller}>
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>
<View style={styles.controlItem}
onPress={() =>
this.props.changeComponent('One') }>
<Text style={{fontSize: 18, color:colors.General.navtext}}>Friends</Text>
</View>
<View style={styles.controlItem}
onPress={() =>
this.props.changeComponent('Two') }>
<Text style={{fontSize: 18, color:colors.General.navtext}}>Local</Text>
</View>
</ScrollView>
</View>
{this.renderComponent(this.state.componentSelected)}
</View>
)
}
})
var ComponentTwo = React.createClass({
render: function() {
return (
<View style={styles.container}>
<ScrollView showsVerticalScrollIndicator={true}>
<View style={styles.card}>
<CardView
name="Short Name"
fullname="Full Name"
distance="Component Two"
title="Example Title"
message="Lorem Ipsum dolor set blablabla"
score="[Symbol for progress]"
stars="smallthree"
starcolors={colors.General.black}
vouched="Example Vouch" />
</View>
</ScrollView>
</View>
)
}
})
var ComponentOne = React.createClass({
render: function() {
return (
<View style={styles.container}>
<ScrollView showsVerticalScrollIndicator={true}>
<View style={styles.card}>
<CardView
name="Short Name"
fullname="Full Name"
distance="Component Two"
title="Example Title"
message="Lorem Ipsum dolor set blablabla"
score="[Symbol for progress]"
stars="smallthree"
starcolors={colors.General.black}
vouched="Example Vouch" />
</View>
</ScrollView>
</View>
)
}
})
The error that is being returned is unexpected token at line 75, which is at the render function of the first component in the code (i.e. at "var ComponentTwo"). And I have no idea why, I have looked for missing commas or semicolons for a while, but I am lost.
The answer to the question was both to remove the excess View tag as the comment to the original question stated, and the fact that the onPress property was not passed via props so it was written as
onPress={() => this.changeComponent('One') }.
But I had also forgotten to add a module.exports.
Thank you!

Categories