How can I generate HTML by function and render it later in JS React

Mikołaj Mrózek :

I'm strugling with generating periodic table in HTML from information given in this.periodicTable[] and rendering it later, as you can see in code below. How can I make it work? Firstly i have made it by hand (all in render() section written in HTML), but later I found out that generating it would be better idea. Everything worked until i switched to generating html istead of writting it. I also would like to use periodicTable data in other parts of website so this one is necessary

importing React stuff

class PeriodicTable extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            show: true,
        };
        this.periodicTable = [
            //    1 row
            this.hydrogen = {
                blank: false,
                name: "hydrogen",
                short: "H",
                z: 1,
                mass: 1.006,
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank:true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.blank = {
                blank: true
            },
            this.hellium = {
                blank: false,
                name: "hellium",
                short: "He",
                z: 2,
                mass: 4.0026,
            },
            //    2 row
        ]
        this.output = "";
    }

    generatePeriodicTable = () =>{
        for(let i = 0; i < this.periodicTable.length; i++){
            if(this.periodicTable[i].blank){
                this.output += <div class = "periodicCard" class="blank"></div>;
            }else{
                this.output +=
                <div class="periodicCard">
                    <sup class="periodicZ">{this.periodicTable[i].z}</sup>
                    <div class='center'>
                        <strong class="periodicElement">{this.periodicTable[i].short}</strong>
                    </div>
                    <div class='center'>
                        <p class="periodicMass">{this.periodicTable[i].mass}</p>  
                     </div>
                </div>;
            }
        }
        return this.output;
    }

    showLearnItPage = () =>{
        this.setState({show: false});
    }

    render(){
        if(this.state.show){
            return(
                <div>
                    <h2>Periodic<sup class="sup">table</sup></h2>
                    <main class="biggrid">
                        {this.generatePeriodicTable}{this.output}
                    </main>
                    <div class='center'>
                        <button class='periodic-table-page-button' onClick={this.showLearnItPage}>Back</button>
                    </div>
                </div>
            );
        }else{
           return( <LearnItPage /> );
        }
    }
}

export default PeriodicTable;```

Gabriel Carneiro :

Ok, so I fixed your code and I'll comment all that I did.

// periodicTable doesn't need to be part of the PeriodicTable Component, Juan Marco has made a good sugestion to stract it to a JSON
// for now I'll just put it in a variable outside PeriodicTable
const periodicTable = [
  //    1 row
  {
      blank: false,
      name: "hydrogen",
      short: "H",
      z: 1,
      mass: 1.006,
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank:true
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank: true
  },
  {
      blank: false,
      name: "hellium",
      short: "He",
      z: 2,
      mass: 4.0026,
  },
  //    2 row
];

// I've created a new Component that will handle the elements rendering, it's just a Function Component
function TableElement(props) {
  const { elementData } = props;
  const { blank, z, short, mass } = elementData;

  if (blank) return <div className="periodicCard blank" />; // take note that in JSX files, HTML classes are className

  return (
    <div className="periodicCard">
        <sup className="periodicZ">{z}</sup>
        <div className='center'>
            <strong className="periodicElement">{short}</strong>
        </div>
        <div className='center'>
            <p className="periodicMass">{mass}</p>  
        </div>
    </div>
  );
}

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

        this.state = {
            show: true,
        };
    }

    // React knows how to handle arrays of ReactComponents, but you must put a key in each element of the array
    generatePeriodicTable = () => {
      return periodicTable.map((el, i) => <TableElement elementData={el} key={i} />);
    }

    showLearnItPage = () => {
        this.setState({ show: false });
    }

    render() {
        if(this.state.show) {
            return (
                <div>
                    <h2>Periodic<sup className="sup">table</sup></h2>
                    <main className="biggrid">
                        {this.generatePeriodicTable()}
                    </main>
                    <div className='center'>
                        <button className='periodic-table-page-button' onClick={this.showLearnItPage}>Back</button>
                    </div>
                </div>
            );
        }
        // after an if with a return you don't need to use else
        return <LearnItPage />;
    }
}

export default PeriodicTable;

Now everything should work as you intended. Take some time to read the React Tutorial.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=391058&siteId=1