54

I want to make a list of fields depending on the number of the player that user has selected. I wanted to make something like this:

generatePaymentField() {
    var noGuest = this.state.guest;
    var payment = 
    <View>
        <View>
            <View><Text>No</Text></View>
            <View><Text>Name</Text></View>
            <View><Text>Preference</Text></View>
        </View>;
        
    for (var i=0; i < noGuest; i++) {
        payment = payment + 
            <View>
                <View>
                    <TextInput />
                </View>
                <View>
                    <TextInput />
                </View>
                <View>
                    <TextInput />
                </View>
            </View>;
    }
    return payment;
}

render () {
    var payment = this.generatePaymentField();
    this.setState({payment : payment});
    return (
        <View>
            {this.state.payment}
        </View>;
    )
}

But react-native regarded the syntax above as 'unexpected token' pointing at the for loop line. Is there any other way I can achieve doing this?

Flair
  • 2,609
  • 1
  • 29
  • 41
Kelvin
  • 873
  • 2
  • 9
  • 20

8 Answers8

99

This should work

render(){

 var payments = [];

 for(let i = 0; i < noGuest; i++){

  payments.push(
   <View key = {i}>
    <View>
     <TextInput />
    </View>
    <View>
     <TextInput />
    </View>
    <View>
     <TextInput />
    </View>
   </View>
  )
 }
 
 return (
  <View>
   <View>
    <View><Text>No</Text></View>
    <View><Text>Name</Text></View>
    <View><Text>Preference</Text></View>
   </View>

   { payments }
  </View>
 )
}
vinay
  • 2,934
  • 1
  • 25
  • 18
  • Oh I see. So in react-native, things like payment = payment + ... do not exist? We have to actually treat them like array? – Kelvin Jan 07 '16 at 06:50
  • You can still use `+`, i have used Array for simplicity. You can use regular javascript. – vinay Jan 07 '16 at 06:52
  • Hmmmm. Then can you elaborate on why my earlier code did not work? Another question is that now it gives me warning about needing keys for each item, where should I put the key? – Kelvin Jan 07 '16 at 06:57
  • I have edited my answer with key. Can you post your complete code so i can take a look – vinay Jan 07 '16 at 07:02
  • I have edited the question, so you can take a look. Actually I omitted some irrelevant code to the question. – Kelvin Jan 07 '16 at 07:17
  • Firstly, you shouldnt use setState inside render. Regarding looping, maybe this post will help you http://stackoverflow.com/questions/22876978/loop-inside-react-jsx – vinay Jan 07 '16 at 07:21
  • Yeah, actually the one who calls the generatePaymentField function & setState is inside another function. I just omit that out. Okay thanks for the help, Vinay! – Kelvin Jan 07 '16 at 07:26
  • this answer lacks explanation. at least explaining that a jsx node is not a string. – Antoine Sep 16 '19 at 14:51
8
render() {
var myloop = [];

for (let i = 0; i < 10; i++) {
  myloop.push(
    <View key={i}>
    <Text>{i}</Text>
    </View>
  );
}

 return (
      
        <View >
          <Text >Welcome to React Native!</Text>
           {myloop}
        </View>
       
      
    );
  }
}
Flair
  • 2,609
  • 1
  • 29
  • 41
Karan KJ
  • 131
  • 1
  • 8
  • Welcome to SO! Your answer will be much better if you explain (1) why the OP's code does not work. No answers did address that direct question, and recommended different techniques to use, which is good and teaches better patterns, but no one pinpointed the OP's error, which is an extra opening in line 4. (2) Since the question has an accepted answer and is old, you must add a few words why do you think your answer is a valuable addition. To me, it looks nearly same as the accepted one, so don't be surprised if yours gets downvoted! Thanks, and good luck at SO! – kkm inactive - support strike Dec 14 '18 at 05:56
2

 render() {
var myloop = [];

for (let i = 0; i < 10; i++) {
  myloop.push(
    <View key={i}>
    <Text style={{ textAlign: 'center', marginTop: 5 }} >{i}</Text>
    </View>
  );
}

 return (

        <View >
          <Text >Welcome to React Native!</Text>
           {myloop}
        </View>


    );
  }

Output 1 2 3 4 5 6 7 8 9

Flair
  • 2,609
  • 1
  • 29
  • 41
Keshav Gera
  • 10,807
  • 1
  • 75
  • 53
1

First of all, I recommend writing the item you want to render multiple times (in your case list of fields) as a separate component:

function Field() {
    return (
        <View>
            <View>
                <TextInput />
            </View>
            <View>
                <TextInput />
            </View>
            <View>
                <TextInput />
            </View>
        </View>
    );
}

Then, in your case, when rendering based on some number and not a list, I'd move the for loop outside of the render method for a more readable code:

renderFields() {
    const noGuest = this.state.guest;
    const fields = [];
    for (let i=0; i < noGuest; i++) {
        // Try avoiding the use of index as a key, it has to be unique!
        fields.push(
            <Field key={"guest_"+i} />
        );
    }
    return fields;
}

render () {
    return (
        <View>
            <View>
                <View><Text>No</Text></View>
                <View><Text>Name</Text></View>
                <View><Text>Preference</Text></View>
            </View>
            {this.renderFields()}
        </View>;
    )
}

However, there are many more ways to render looped content in react native. Most of the ways are covered in this article, so please check it out if you're interested in more details! The examples in article are from React, but everything applies to React Native as well!

Flair
  • 2,609
  • 1
  • 29
  • 41
Nesha Zoric
  • 6,218
  • 42
  • 34
0

You can create render the results (payments) and use a fancy way to iterate over items instead of adding a for loop.

const numberOfGuests = 3;

Array(numberOfGuests).fill(noGuest).map(guest => console.log(guest));

Example:

renderPayments(numberOfGuests) {
  return Array(numberOfGuests).fill(numberOfGuests).map((guest, index) => {
    return(
      <View key={index}>
        <View><TextInput /></View>
        <View><TextInput /></View>
        <View><TextInput /></View>
      </View>
    );
  }
}

Then use it where you want it

render() {
  return(
     const { guest } = this.state;
     ...
     {this.renderPayments(guest)}
  );
}

Hope you got the idea.

If you want to understand this in simple Javascript check Array.prototype.fill()

Abraham
  • 8,525
  • 5
  • 47
  • 53
0
renderItem(item)
  {
    const width = '80%';
    var items = [];

    for(let i = 0; i < item.count; i++){

        items.push( <View style={{ padding: 10, borderBottomColor: "#f2f2f2", borderBottomWidth: 10, flexDirection: 'row' }}>
    <View style={{ width }}>
      <Text style={styles.name}>{item.title}</Text>
      <Text style={{ color: '#818181', paddingVertical: 10 }}>{item.taskDataElements[0].description + " "}</Text>
      <Text style={styles.begin}>BEGIN</Text>
    </View>

    <Text style={{ backgroundColor: '#fcefec', padding: 10, color: 'red', height: 40 }}>{this.msToTime(item.minTatTimestamp) <= 0 ? "NOW" : this.msToTime(item.minTatTimestamp) + "hrs"}</Text>
  </View> )
  }

  return items;
}

render() {
return (this.renderItem(this.props.item)) 
}
Flair
  • 2,609
  • 1
  • 29
  • 41
Apurva Aggarwal
  • 296
  • 3
  • 10
0
render(){

    var payments = [];

    for(let i = 0; i < noGuest; i++){

        payments.push(
            <View key = {i}>
                <View>
                    <TextInput />
                </View>
                <View>
                    <TextInput />
                </View>
                <View>
                    <TextInput />
                </View>
            </View>
        )
    }
    
    return (
        <View>
            <View>
                <View><Text>No</Text></View>
                <View><Text>Name</Text></View>
                <View><Text>Preference</Text></View>
            </View>

            { payments }
        </View>
    )
}
D99
  • 84
  • 6
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 27 '21 at 06:53
0

render(){

    var payments = [];

    for(let i = 0; i < noGuest; i++){

        payments.push(
            <View key = {i}>
                <View>
                    <TextInput />
                </View>
                <View>
                    <TextInput />
                </View>
                <View>
                    <TextInput />
                </View>
            </View>
        )
    }
    
    return (
        <View>
            <View>
                <View><Text>No</Text></View>
                <View><Text>Name</Text></View>
                <View><Text>Preference</Text></View>
            </View>

            { payments }
        </View>
    )
}

render(){

    var payments = [];

    for(let i = 0; i < noGuest; i++){

        payments.push(
            <View key = {i}>
                <View>
                    <TextInput />
                </View>
                <View>
                    <TextInput />
                </View>
                <View>
                    <TextInput />
                </View>
            </View>
        )
    }
    
    return (
        <View>
            <View>
                <View><Text>No</Text></View>
                <View><Text>Name</Text></View>
                <View><Text>Preference</Text></View>
            </View>

            { payments }
        </View>
    )
}

render(){

    var payments = [];

    for(let i = 0; i < noGuest; i++){

        payments.push(
            <View key = {i}>
                <View>
                    <TextInput />
                </View>
                <View>
                    <TextInput />
                </View>
                <View>
                    <TextInput />
                </View>
            </View>
        )
    }
    
    return (
        <View>
            <View>
                <View><Text>No</Text></View>
                <View><Text>Name</Text></View>
                <View><Text>Preference</Text></View>
            </View>

            { payments }
        </View>
    )
}