react native can't assign simple variable - javascript

I have the weirdest (i'm sure it's simple) bug with react native.
I am using Parse for the backend. getting a parse object and trying to render a react object from it's attributes. simple.
renderRow(rowData, sectionID, rowID) {
console.log(rowData);
var data = rowData._serverData;
var photo_url = rowData._serverData.photo_url;
return (
<TouchableHighlight onPress={() => this.rowPressed(rowData.guid)}
underlayColor='#dddddd'>
<View>
<View style={styles.rowContainer}>
<Image style={styles.thumb} source={{ uri: photo_url }} />
<View style={styles.textContainer}>
<Text style={styles.title}>{rowData._serverData.badge}</Text>
<Text style={styles.description}
numberOfLines={2}>{rowData._serverData.description}</Text>
</View>
</View>
<View style={styles.separator}/>
</View>
</TouchableHighlight>
);
}
I'm getting cannot read property 'photo_url' of undefined for this row
var photo_url = rowData._serverData.photo_url;.
this thing is , the data is there, I have made sure with the chrome debugger.

turns out there is something weird with Parse.
doing this:
rowData.attributes.photo_url
solved it. I have to say i'm not quite sure why.

Related

I need to make a loop from 1 to 100 in scrollview But i cant

This is the code but I cant write 1 to 100 like that so I need a loop but there are some errors about which I don't know anything I don't know how to resolve this issue. Help me to get through this...
<ScrollView
vertical={true}
style={styles.scroller}
showsHorizontalScrollIndicator={true}
showsVerticalScrollIndicator={true}>
<Text style={styles.welcome}> 1</Text>
<Text style={styles.welcome}> 2</Text>
<Text style={styles.welcome}> 3</Text>
<Text style={styles.welcome}> 4</Text>
<Text style={styles.welcome}> 5</Text>
<Text style={styles.welcome}> 6</Text>
<Text style={styles.welcome}> 7</Text>
<Text style={styles.welcome}> 8</Text>
<Text style={styles.welcome}> 9</Text>
<Text style={styles.welcome}> 10</Text>
</ScrollView>
The above code is working but, If I use for loop instead of this 'Text' thing I get the error.
for (let i = 0; i < 100; i++) {
<Text>{i}</Text>
Error on the number '100' it says: Identifier expected.
For a larger data set it is advised to use a FlatList in react-native. This is done relatively easy by introducing a state that holds the data.
Here is a minimal example.
const FlatListExample = (props) => {
// prefill the state with 100 objects
const [data, setData] = useState(Array(100).fill().map((_, i) => i+1))
return (
<FlatList
data={data}
keyExtractor={(item) => item.toString()}
renderItem={({item, index}) => {
return <Text style={styles.welcome}>{item}</Text>
}}
/>
)
}
A FlatList is a convenient wrapper around ScrollView and is generally speaking the better choice for larger data sets when it comes to performance.
If you still want to use a ScrollView, then you can just use the map function as follows.
const data = useMemo(() => Array(100).fill().map((_, i) => i+1), [])
<ScrollView
style={styles.scroller}>
{
data.map(i => <Text style={styles.welcome}>{i}</Text>)
}
</ScrollView>

Warning: Cannot update a component from inside the function body of a different component. in TouchableOpacity

I got this error
Warning: Cannot update a component from inside the function body of a different component.
How to fix this ?
When I remove touchable opacity, it's not showing anymore
<View style={styles.SaD}>
<TouchableOpacity onPress={(e) = props.locationSetState(1)}> // here
<Text style={styles.text1}>Choose your starting point</Text>
</TouchableOpacity>
<TouchableOpacity onPress={(e) = props.locationSetState(2)}>
<Text style={styles.text1}>Choose destination</Text>
</TouchableOpacity>
</View>
details are not sufficient to understand your problem but according to what I understand from your code try using react hooks and try this
function App() {
const [state,setState]=React.useState(null);
console.log(state);
return (
<View style={styles.SaD}>
<TouchableOpacity onPress={(e) => setState(1)}>
<Text style={styles.text1}>Choose destination</Text>
</TouchableOpacity>
<TouchableOpacity onPress={(e) => setState(2)}>
<Text style={styles.text1}>Choose destination</Text>
</TouchableOpacity>
</View>
);
}

Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of 'search'

The search is perfect and it's all looks fine, but gets this warning.
I get this warning when I press any key to start the search method.
"Song_ID", "Song_Name" and "Image" are of the variable names from the SQL Database.
- I looked on other question as this, but it didn't help me at all.
This is the code where the error is :
return (
<View>
<ScrollView>
{musicList.map(songObj => {
return (
<View style={styles.resultsContainer}> /// Its written that the erorr in this line
<TouchableOpacity onPress={this.GetListViewItem.bind(this, songObj.Song_Name)}>
<Text style={{ fontSize: 16 }} key={songObj.Song_ID}>
{songObj.Song_Name}</Text>
<Image source={{ uri: songObj.Image }} style={styles.img} />
</TouchableOpacity>
</View>
);
})}
</ScrollView>
</View>
);
}
I don't understand where to put the key and/or what does it mean, I tried so many times but it didn't went well.
If more details is needed please tell me and I'll insert the right code.
You should add the key onto the outermost component inside the map. In your case, this is the View. Try this:
return (
<View>
<ScrollView>
{musicList.map(songObj => {
return (
<View style={styles.resultsContainer} key={songObj.Song_ID}>
<TouchableOpacity onPress={this.GetListViewItem.bind(this, songObj.Song_Name)}>
<Text style={{ fontSize: 16 }}>
{songObj.Song_Name}</Text>
<Image source={{ uri: songObj.Image }} style={styles.img} />
</TouchableOpacity>
</View>
);
})}
</ScrollView>
</View>
);
}
Adding the key prop lets react optimize rendering which is why it recommends you add it. Read the docs for more info.

React-native: Pass event to other object

This is my first experience with JS/React/React Native. I don't yet fully grasp mechanics of this framework, so be kind to me.
What I have :
<View style={styles.container}>
<View style={styles.timerContainer}>
<View style={styles.timerBar}>
<Image style={styles.icon} source={require('../../img/time50.png')}/>
{Timer} //First
</View>
<View style={styles.timerBar}>
<Image style={styles.icon} source={require('../../img/break50.png')}/>
{Timer} //Second
</View>
</View>
<View style={styles.buttonContainer}>
<TouchableHighlight onPress={this.startWork}>
<Image style={styles.imageButton} source={require('../../img/start.png')}/>
</TouchableHighlight>
<TouchableHighlight onPress={this.startBreak}>
<Image style={styles.imageButton} source={require('../../img/break.png')}/>
</TouchableHighlight>
<TouchableHighlight onPress={this.stopWork}>
<Image style={styles.imageButton} source={require('../../img/end.png')}/>
</TouchableHighlight>
</View>
</View>
Timer is a custom class, which will have 'start', 'pause' and 'end' methods. I want to call methods of both Timers when TouchableHighlight is pressed.
Overall it would look like this :
when first TouchableHighlight is pressed (startWork), Timer2.end and Timer1.start should be called, when second is pressed (startBreak), Timer1.pause, Timer2.start should be called, for third (stopWork) it would be Timer1.end, Timer2.end.
But how am I supposed to refer to these timers from onPress methods? Should I keep both Timers in some vars of parent class? I am totally stuck and have no idea where to start (and what's acceptable). Such problem is not easily googlable (or I don't know where to look). I would appreciate any help (solution, pointing to tutorial...).
When you render the timer components in this component you should assign a ref to each one of them, like
<Timer ref={r => this.timer1 = r}/>
Then in the Touchable callback functions you can call this.timer1.start()
Note: Cleaner ref setting would be to actually have another function, so you aren't constantly binding in the render function:
setTimerOne = (r) => {
this.timer1 = r;
}
render() {
<Timer ref={this.setTimerOne}/>
}

React Native : set id to a component and get this component's id

I am developing my first React Native app and I am trying to set an id to a component so that I can determine this view when pressing on it and displaying data according to the component's id
This is what I tried so far:
renderRow(rowData, sectionID, rowID){
var past_matches_circles =[];
for(var i=0; i<isPast; i++){
past_matches_circles.push(
<TouchableOpacity id={i} key = {i} collapsable={false} style={styles.small_circle} onPress={()=>this.pressOnCircle(rowData[`${i}`].MatchID)}>
</TouchableOpacity>
);
}
return (
<View>
<View style={{flexDirection:'row'}}>
{past_matches_circles}
</View>
<View style={{flexDirection:'row'}}>
<Image style={{width:100, height:100, margin:5}} source={{uri:'http://facebook.github.io/react/img/logo_og.png'}}/>
<View style={{justifyContent:'center', flex:1}}>
<Text> {rowData[0].MatchDate} </Text>
<Text> {rowData[0].HomeTeam} VS {rowData[0].AwayTeam} </Text>
</View>
</View>
</View>
);
}
pressOnCircle(i){
ToastAndroid.show('key ' + i, ToastAndroid.SHORT);
}
but unfortunately the iterator i value is always equal to its last value inside the loop regardless which view I am pressing on.
Can anyone help me getting component's id?
After several days, finally I solved this problem. And I'll post it for who will come to this question.
I was pushing the views into my array without returning so the value of i is always the same.
so that what I did:
renderCircle(id) {
return <TouchableOpacity key={id} style={styles.small_circle} onPress={() => this.pressOnCircle(id)}>
</TouchableOpacity>;
}
renderRow(rowData, sectionID, rowID){
var past_matches_circles =[];
for(var i=0; i<isPast; i++){
past_matches_circles.push(
this.renderCircle(i)
);
}
var { page, animationsAreEnabled } = this.state;
return (
<View>
<View style={{flexDirection:'row'}}>
{past_matches_circles}
</View>
<View style={{flexDirection:'row'}}>
<Image style={{width:100, height:100, margin:5}} source={{uri:'http://facebook.github.io/react/img/logo_og.png'}}/>
<View style={{justifyContent:'center', flex:1}}>
<Text> {rowData[0].MatchDate} </Text>
<Text> {rowData[0].HomeTeam} VS {rowData[0].AwayTeam} </Text>
</View>
</View>
</View>
);
}
Hope that will help.
You can use .bind to create a new function that closes over the value of i. This isn't the best for performance as you're creating a new function each time.
onPress={ this.pressOnCircle.bind(this, i) }>
Also, you might need to do something like
this.pressOnCircle = this.pressOnCircle.bind(this);
In the constructor to get the proper this context in the handler.

Categories

Resources