Basic Concepts

After running through a tic-tac-toe tutorial it became very obvious to me that ReactJS is a kind of server faces technology but runs in the client context instead.  When you use JSX to define classes, these classes become new HTML elements that can be used like any other element.  You write your page in JSX and it compiles down to regular JavaScript.  The main idea behind ReactJS is to allow developers to create reactive programmable components than can be dropped into your HTML pages.  It's really the View in the MVC.

Basically each component should be structured as follows

ReactJS Class
class Square extends React.Component {
  render() {
    return (
      <button className="square">
        {/* TODO */}
      </button>
    );
  }
}

The attribute className represents a class style in a .css file.

The return keyword, returns a DOM element that ReactJS can render.

All ReactJS components have a this.props.<field>.  As with all JS variables these can be created dynamically, consider the following lines of code

Sample code -properties being passed
class Square extends React.Component {
  render() {
    return (
      <button className="square" onClick={()=>alert('click')}>
        {this.props.value}
      </button>
    );
  }
}

class Board extends React.Component {
  renderSquare(i) {
    return <Square value={i}/>;
  }

At line 13 return <Square value={i}/>; value={i] could be changed to selsVal={i}, but line 5 {this.props.value} would need to change to {this.props.selsVal}.  The above example is a demonstration of how property values are passed between components in ReactJS

State

React components can have state by setting this.state in their constructors. this.state should be considered as private to a React component that it’s defined in.

Eureka Moment

Line 13 in the above code fragment explains a lot.  Unlike traditional programming where each function call leads onto another function call, and the end of the chain of calls would yield a result.  In this model, line 13 returns an object of type Square.  But line 13 can be considered like a remember object/a future object, a Square is instantiated with a value in the 'i' variable, this value is passed to the Square constructor that looks like this

class Square extends React.Component {
   constructor(props)
   {
      super(props);
      this.state = {
      value: null
   }
}

So this line - <Square value={i}/> can be considered as performing a call like Square( i ). To access the passed parameter in the constructor you could write

class Square extends React.Component {
   constructor(props)
   {
      super(props);
      this.state = {
      value: props.value
   }
}

If you change line 13 to <Square value={i} index={i + 1}/>, you are now passing two parameters to the constructor Square(i, i + 1).  To access these parameters in the constructor you would write

class Square extends React.Component {
   constructor(props)
   {
      super(props);
      this.state = {
      value: props.value,
            idx : props.index
   }
}
Notice that each constructor parameter is available in the props object.  

The Square class now looks like this:
class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
    };
  }

  render() {
    return (
      <button
        className="square"
        onClick={() => this.setState({value: 'X'})}
      >
        {this.state.value}
      </button>
    );
  }
}

The Board's renderSquare method will change to

renderSquare(i) {
    return <Square value={this.state.squares[i]} />;
  }

In the tic-tac-toe example, the state of the game (state of each square is being kept in the board even though each square maintains it's own state.  The designer has decided for simplicity's sake it will be easier to keep the games state in the board rather than the square.  Since this is a ReactJS learning exercise I would agree, this is not about OO design principles.

Lambdas

There is a lot of fuss around at the moment in regards to lambdas.  Essentially a lambda is a function that can be passed around as a piece of data.  The syntax used by most programming language is more about syntactic sugar ()=>{code block}.  Way back in the day when the majority of my software development was in C++, we called such functions "functors" or "function object".  The syntax wasn't elegant, it required the use of template classes and inheritance.  C++ now has a lambda expression.

Lambdas are useful for a number of things, but one of the useful features is to create a callback (a function that is called at another point in your code when an event occurs.  The callback is defined in an object whose state the event handler wants to change.  In the board example, we are going to create a lambda in the board, pass this lambda to the square, when the square is clicked it will call the lambda to update the state of the board.

The use of lambdas in this manner is an important part of ReactJS programming.

Here is the modification to the game

Code fragment
//The board now has a constructor
// the state.squares field has 0..8 entries with the following values 'O', 'X', null - null means an unoccupied square

class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
    };
  }

//Once again we will modify the Board's renderSquare method to
renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }
// notice we are passing two parameters to the Squares constructor via the props field.  Notice the onClick={() => this.handleClick(i)} it's a lambda being passed to the onClick field.

When you run this application you will get a runtime error, "TypeError: _this4.handleClick is not a function".  We defined a lambda to a function that doesn't yet exist (something that couldn't happen in languages like C++, Java, C#, Object Pascal, etc.  So let's add the method

Code Sample


class Board extends React.Component {
...
 handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = 'X';
    this.setState({squares: squares});
  }