4

I ran forEach inside the render block and it outputs normally on the console, but the text tag is not displayed on the output.

What is the problem?

import React from "react";
import { StyleSheet, Text, View } from "react-native";

class Lotto extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      count: 6,
      maxNum: 45
    };

    this.lottoSet = this.createLottoNumber();
  }

  createLottoNumber() {
    let lottoSet = new Set();
    let rNum;

    for (let i = 0; i < this.state.count; i++) {
      rNum = Math.round(Math.random() * (this.state.maxNum * 1) + 1);
      if (lottoSet.has(rNum)) i--;
      else lottoSet.add(rNum);
    }

    return lottoSet;
  }

  render() {
    return (
      <View style={styles.container}>
        {this.lottoSet.forEach(n => {
          console.log(`<Text style={styles.item}>${n.toString()}</Text>`);
          return <Text style={styles.item}>{n.toString()}</Text>;
        })}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#333",
    flexDirection: "row",
    paddingTop: "10%",
    justifyContent: "center"
  },
  item: {
    color: "#fff",
    textAlign: "center",
    width: "100px"
  }
});

export default Lotto;
Hamed
  • 5,867
  • 4
  • 32
  • 56
ChoiHanGyu
  • 43
  • 1
  • 4
  • Looks like a duplicate of https://stackoverflow.com/questions/47442462/reactjs-map-works-but-foreach-doesnt. Don't worry this is a very common mistake people make. Including me 5 years ago, you can check my questions back in 2015. – Jon Miles Mar 18 '20 at 07:39

2 Answers2

4

You must use map instead to render elements.

render() {
    return (
      <View style={styles.container}>
        {this.lottoSet.map(n => (
          <Text key={n.toString()} style={styles.item}>{n.toString()}</Text>
        ))}
      </View>
    );
  }

React is declarative and takes a declaration of view state to render, map will build a declared, immutable view state. Whereas using forEach has potential to create side effects outside of the render method, thus is not supported.

bbullis
  • 532
  • 7
  • 20
Jon Miles
  • 9,605
  • 11
  • 46
  • 66
2

forEach does not return a value, but stands for executing side effects on each array element. Instead, you are looking for map:

  <View style={styles.container}>
    {this.lottoSet.map(n => {
      console.log(`<Text style={styles.item}>${n.toString()}</Text>`);
      return <Text key={n.toString()} style={styles.item}>{n.toString()}</Text>;
    })}
  </View>

Also, note that I add a key prop to each Text element, you can read about it here: https://reactjs.org/docs/lists-and-keys.html

BTW, the fact that you called createLottoSet in the constructor once, meaning that it won't be generated on every change of state.

Hamed
  • 5,867
  • 4
  • 32
  • 56
MorKadosh
  • 5,846
  • 3
  • 25
  • 37