Files created by create-react-app

The file we should focus now is App.js. This file out of the box contains the following code:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and
          save to reload.
        </p>
      </div>
    );
  }
}

export default App;

Let’s wipe out the bulk of this code and just replace it with a simple render of the Table component (which we’ll implement next).

We pass it 2 properties: x the number of columns and y the number of rows.

import React from 'react'
import Table from './components/Table'

const App = () =>
  (<div style={{ width: 'max-content' }}>
    <Table x={4} y={4} />
  </div>)

export default App

Here’s the Table component, which we store in components/Table.js:

import React from 'react'
import Row from './Row'

export default class Table extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      data: {},
    }
  }

  handleChangedCell = ({ x, y }, value) => {
    const modifiedData = Object.assign({}, this.state.data)
    if (!modifiedData[y]) modifiedData[y] = {}
    modifiedData[y][x] = value
    this.setState({ data: modifiedData })
  }

  updateCells = () => {
    this.forceUpdate()
  }

  render() {
    const rows = []

    for (let y = 0; y < this.props.y + 1; y += 1) {
      const rowData = this.state.data[y] || {}
      rows.push(
        <Row
          handleChangedCell={this.handleChangedCell}
          updateCells={this.updateCells}
          key={y}
          y={y}
          x={this.props.x + 1}
          rowData={rowData}
        />,
      )
    }
    return (
      <div>
        {rows}
      </div>
    )
  }
}

The Table component manages its own state. Its render() method creates a list of Row components, and passes to each one the part of state that bothers them: the row data. The Row component will in turn pass this data down to multiple Cell components, which we’ll introduce in a minute.

We use the y row number as the key property, which is mandatory to distinguish multiple rows.

We pass to each Row component the handleChangedCell method as a prop. When a row calls this method, it passes an (x, y) tuple indicating the row, and the new value that’s been inserted into it, and we update the state accordingly.


Go to the next lesson