1

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;```

  • 1
    Why not first create a separate file formatted as a JSON object that contains all the elements of the periodic table? How you structure the info inside that object is up to you. Once this is done, you can import the JSON file into your React app and then generate the table dynamically. – Juan Marco Apr 02 '20 at 15:03
  • Ok, your code have a lot of problems, you're using React Components as if it was strings containing HTML, and this is not the way React works. The function `generatePeriodicTable` will never work. – Gabriel Carneiro Apr 02 '20 at 15:06
  • Ok, that's good idea to do first @JuanMarco . Thanks. I didnt even thing about it because I'm not similar with using JSON. I know it sounds crazy, but this wasnt that obvious for me. I'm programming for fun. So for now I'm learning from my mistakes. I will come back after transfering data to JSON – Mikołaj Mrózek Apr 02 '20 at 15:22

1 Answers1

1

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.

Gabriel Carneiro
  • 643
  • 5
  • 16
  • I'm not really understand how this notation works: `periodicTable.map((el, i) => )`, but it solved my problem. I'll read the link u sent me. Thanks for help! – Mikołaj Mrózek Apr 02 '20 at 15:39
  • @MikołajMrózek take a look [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) to understand about array map. – Gabriel Carneiro Apr 02 '20 at 15:45
  • @MikołajMrózek take a look [here](https://reactjs.org/docs/lists-and-keys.html) to understand how React deals with lists of React Elements – Gabriel Carneiro Apr 02 '20 at 15:48
  • I will, definitely. Once again, thanks for help. I just transfered data to .json file so I'm on good way to success at this project. – Mikołaj Mrózek Apr 02 '20 at 15:59