user3576724 user3576724 - 3 months ago 13
React JSX Question

Having trouble enumerating a ListView in React Native

I just started React JS so I'm not used to the syntax.

Basically, long story short, I don't know where to put the number++ iterator. I want my number to increment every time a new list item row is added in my this.state = {rank:number}

This should be simple but I can't seem to figure out how to insert number iteration function into my ListView. Please help!

Also, if you also know how to sort the ListView by score, that would help me a great deal with my project. I'm all ears.

Here is my code:

const users = [
{id:1, name: "Jerry Love", score: 12},
{id:2, name: "Bob Billy", score: 10},
{id:3, name: "Santana Diego", score: 1},
{id:4, name: "Thompson Merlin", score: 6},
{id:5, name: "Harold Davis", score: 3},
{id:6, name: "Raritan Junior", score: 9},
{id:7, name: "Caroline Anderson", score: 19},
{id:8, name: "Haly Edison", score: 14},

]

class GlobalRankView extends Component {
constructor(props){
super(props)
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2})
this.state = {
rank: number,
matchedusersDataSource: ds.cloneWithRows(users)
}
}

render() {
return (
<View style={styles.rankingContainer}>
<View style={styles.rankingHeaderRow}>
<Text style={styles.headerText}>Rank</Text>
<Text style={styles.headerText}>User</Text>
<Text style={styles.headerText}>Trophies</Text>
</View>
<ListView
dataSource={this.state.matchedusersDataSource}
renderRow={(user) => { return this.renderuserRow(user) }}
>
</ListView>
</View>
)
}

renderuserRow(user) {
return(
<View style={styles.userRow}>
<Text>{this.state.rank}</Text>
<View styles={styles.userColumn}>
<Text style={styles.userName}> {user.name}</Text>
<Text style={styles.userDistance}> {user.score}</Text>
</View>
</View>
)
}
}



Answer

Your problem is not about using the ListView of react-native, you are basically having problems with the concept of state and props in React.

For what I understood, you are saying that you have a list of items where you can add additional ones. First of all, I would make my state simpler:

this.state = {
  users
}

You don't need that rank in your state since that can be just calculated using this.state.users.length. Thus your can do:

In your renderUserRow:

// Change this
<Text>{this.state.rank}</Text>
// For
<Text>{this.state.users.length}</Text>

In your render() function:

render() {
  return (
    ...
    const data = dataSource.cloneWithRows(this.state.users)
    <ListView
       dataSource={data}
       renderRow={(user) => { return this.renderuserRow(user) }}
    >
    ...

Bonus point 1: You can define outside of your component:

const dataSource = new ListView.DataSource({
  rowHasChanged: (r1, r2) => r1.id !== r2.id,
});

Notice the id comparison, it will make your life easier.

Bonus point 2: You don't want to use cloneWithRows every time you re-render? Check out https://github.com/reactjs/redux/issues/683 (although I doubt it would be an issue).


Another possibility is that you want this rank to start at 0 and then increment it every time you add a new item into the list. Then:

this.state = {
  rank: 0,
  users
}

When you add a user, at some place in your code you would need to call:

this.setState({ rank: this.state.rank + 1 })

What is the problem of sorting ? Imagine you have a button called 'Sort by score', when you click it, it should do something like:

_sortByScores() {
  this.setState({ 
    users: this.state.users.slice().sort((a, b) => a.score - b.score) 
  })
}

Careful here, if you don't call something like slice, the sort would mutate your state directly.