when I put onPress in a map loop, it doesn't work. how to fix it?
var PageOne = React.createClass({
_handlePress() {
this.props.navigator.push({id: 2,});
},
render () {
return (
<View>
<TouchableOpacity onPress={this._handlePress}> //work here
<Text> One </Text>
</TouchableOpacity>
<View style={styles.albums}>
{
list.map(function(item, index){
return (
<TouchableOpacity key={index} onPress={this._handlePress}> //doesn't work hehre
<Text>{item}</Text>
</TouchableOpacity>
)
})
}
</View>
</View>
);
}
});
this is referring to the wrong context, you need the scope to be lexically bound, which is what the fat arrow function will do for you.
Try calling your function like this:
onPress={ () => this._handlePress() }
Also, you need to bind the map function to the correct context like this:
<View style={styles.albums}>
{
list.map(function(item, index){
return (
<TouchableOpacity key={index} onPress={() => this._handlePress()}>
<Text>{item}</Text>
</TouchableOpacity>
)
}.bind(this))
}
</View>
Or like this:
<View style={styles.albums}>
{
list.map((item, index) => {
return (
<TouchableOpacity key={index} onPress={() => this._handlePress()}>
<Text>{item}</Text>
</TouchableOpacity>
)
})
}
</View>
I set up a working project here.
https://rnplay.org/apps/_PmG6Q
Related
I know with the following code below changing a useState within another component's onPress event wouldn't be possible but how would I do it? I want to make it so when the onPress function within Card.js is executed the popUpData from within App.js is changed.
App.js
const [popUpData, setPopUpData] = React.useState("Nothing")
return (
<Card>
<Text style={styles.pokemonName}>{item.name}</Text>
</Card>
<Text>{popUpData}</Text>
)
Card.js
const doSomething = () => {
setPopUpData("Something")
//other things...
}
return (
<TouchableOpacity activeOpacity={1} style={styles.card} onPress={doSomething()}>
<View style={styles.cardContent}>
{ props.children }
</View>
</TouchableOpacity>
)
App.js
const [popUpData, setPopUpData] = React.useState("Nothing")
return (
<Card onUpdate={(d)=>setPopUpData(d) }>
<Text style={styles.pokemonName}>{item.name}</Text>
</Card>
<Text>{popUpData}</Text>
)
Card.js
function Card(props){
const doSomething = () => {
props.onUpdate("Something")
}
return (
<TouchableOpacity activeOpacity={1} style={styles.card} onPress={doSomething()}>
<View style={styles.cardContent}>
{ props.children }
</View>
</TouchableOpacity>
)
}
Just pass reference to setState function down to child component.
(in the simplest scenario)
const Parent = () => {
const [popUpData, setPopUpData] = React.useState("Nothing")
return (
<Card setPopUpDataHandler={setPopUpData}>
<Text style={styles.pokemonName}>{item.name}</Text>
</Card>
<Text>{popUpData}</Text>
)
}
const Card = ({setPopUpDataHandler, children}) => {
const doSomething = () => {
setPopUpDataHandler("Something")
//other things...
}
return (
<TouchableOpacity activeOpacity={1} style={styles.card} onPress={doSomething()}>
<View style={styles.cardContent}>
{ children }
</View>
</TouchableOpacity>
)
}
Problem is I cannot see {item.key} inside my function. When I type {item.key} itself inside flatlist render it is working. But inside function only {item.value} is showing. Can anyone explain to me why this happening ?
Sample Data
const orderResultJson = [
{
key: 'Скачайте приложение по ссылке',
value: 'https://google.com'
},
{
key: 'Логин',
value: '879854'
},
{
key: 'Пароль',
value: '849846'
},
];
My Function
function DetailsSection(item){
return(
<View>
<Text>{item.value}</Text>
<Text>{item.key}+test</Text>
</View>
)
}
Render
render() {
return (
<View style={styles.container}>
<FlatList
data={orderResultJson}
renderItem={({item}) => <DetailsSection {...item} />}
keyExtractor={item => item.key}
/>
</View>
);
}
Problem here is, when you are deconstructing item as individual props, the prop key will be considered as in built react prop key instead of considering it as an external prop.
So instead of deconstructing, pass item as is and access it from your function as it is.
My Function
function DetailsSection({ item }){
return(
<View>
<Text>{item.value}</Text>
<Text>{item.key}+test</Text>
</View>
)
}
Render
render() {
return (
<View style={styles.container}>
<FlatList
data={orderResultJson}
renderItem={({item}) => <DetailsSection item={item} />}
keyExtractor={item => item.key}
/>
</View>
);
}
function DetailsSection(props){
return(
<View>
<Text>{props.item.key} + test</Text>
<Text>{props.item.value}</Text>
</View>
)
}
Or
pass like this
<DetailsSection item={item} />
and access like this
function DetailsSection({ item }){
return(
<View>
<Text>{item.value}</Text>
<Text>{item.key}+test</Text>
</View>
)
}
because you are passing extracted value so directly you can access
I have a ScrollView and referencing it using ref but when I'm calling scrollTo of it, I am getting undefined is not an object.
next = () => {
this.scrollView.scrollTo({x:0, y:0, animated: true});
}
render() {
return(
<View>
<ScrollView ref={component => { this.scrollView = component }}>
<View></View>
<View></View>
<View></View>
</ScrollView>
<TouchableOpacity onPress={() => this.next()}>
<Text>Next</Text>
</TouchableOpacity>
</View>
)
}
The remedies that I have tried but never worked includes
using .bind(this) when calling the function
.bind(this) in the constructor
using refs ref='scrollView' and this.refs.scrollView
using arrow functions
Am I missing something here?
Try this,
next = () => {
this.scrollView.scrollTo({x:0, y:0, animated: true});
}
render() {
return(
<View>
<ScrollView ref={component => { this.scrollView = component }}>
<View></View>
<View></View>
<View></View>
</ScrollView>
<TouchableOpacity onPress={this.next}>
<Text>Next</Text>
</TouchableOpacity>
</View>
)
}
we need only one side binding.
Have parent tag as <TouchableWithoutFeedback> and child as <Image>, trying to change the image source from the parent onPress function, but getting error. how can I archive this using refs? or any other way to resolve it?
React-native version : 0.56
Error :
Cannot read property 'favIcon' of undefined
Sample Code :
const fav = require('../../images/favorite.png');
const nonfav = require('../../images/not_favorite.png');
updateFavorite = (id) => {
this.props.refs.favIcon.source(fav);
}
render(){
return (
<View style={styles.container}>
<TouchableWithoutFeedback onPress={ this.updateFavorite.bind(this, 1) }>
<View style={ styles.imageView }>
<Image refs="favIcon" source={ nonfav } />
</View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={ this.updateFavorite.bind(this, 2) }>
<View style={ styles.imageView }>
<Image refs="favIcon" source={ nonfav } />
</View>
</TouchableWithoutFeedback>
</View>
)
}
Note : change only the child image of onPressed, not all images.
try it using nativeProps, like
import resolveAssetSource from 'resolveAssetSource';
this.refs['favIcon'].setNativeProps({
src: [resolveAssetSource(fav)]
});
refer this for more.
It might not work with react-native 0.50+ versions but according to this comment it should work with 0.57.1
Updating properties of elements in React is best done by calling setState method. Try the following
updateFavorite = (event) => {
event.target.setAttribute('src', fav)
}
render(){
return (
<View style={styles.container}>
<TouchableWithoutFeedback>
<View style={ styles.imageView }>
<img ref={ref => this.favIcon = ref} src={nonFav} onPress={ this.updateFavorite }/>
</View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback>
<View style={ styles.imageView }>
<img ref={ref => this.favIcon = ref} src={nonFav} onPress={ this.updateFavorite } />
</View>
</TouchableWithoutFeedback>
</View>
)
}
I am trying to open an item from my list but my item code is in another js. When I try to use onPress method there is no action. Also I am using Swipeout.
Here is my JobList.js where I am rendering the list of my items.
class JobList extends Component {
onJobDetails = (job) => {
this.props.navigate('JobDetails', job);
}
render() {
const { navigation } = this.props;
var renderJobs = () => {
return this.props.jobs.map((job) => {
return (
<JobItem
key={job._id}
title={job.title}
shortDescription={job.shortDescription}
logo={job.avatar}
company={job.company}
id={job._id}
dispatch={this.props.dispatch}
onPress={() => this.onJobDetails(job)}
/>
)
})
}
return (
<View style={styles.container}>
<ScrollView>
{renderJobs()}
</ScrollView>
</View>
);
}
};
And here is my JobItem.js
class JobItem extends Component {
render() {
return (
<Swipeout {...swipeSettings}>
<View style={styles.jobContainer}>
<View>
<Text style={styles.postTitle}>{this.props.title}</Text>
<Text style={styles.postShortDescription}>{this.props.shortDescription}</Text>
</View>
<View>
<Image
style={styles.postLogo}
source={{uri: '' + this.props.logo + ''}}/>
</View>
</View>
</Swipeout>
)
}
};
Any idea how shall I fix this?
You need to pass onPress prop to the child component in order for it to work.
<Swipeout {...swipeSettings}>
<TouchableWithoutFeedback onPress={this.props.onPress}>
//... other children here
</TouchableWithoutFeedback>
</Swipeout>