Home

React - An Overview

What is React?

React is a declarative, efficient, and flexible JavaScript library for building user interfaces.
It lets you compose complex UIs from small and isolated pieces of code called “components”.

React has a few different kinds of components, first we'll go with React.Component



You can find an MDN Tutorial Document on React Here that may be useful.

Extracts from this are used below...

You can also take a look at w3Schools offering and follow their React Tutorial (also listed in next pane, Set-up Environment)



To create a REACT/NODE.JS set-up using Visual Studio 2019 take a look at the Microsoft Document.


NOTE
When following this document to create a Project in Visual Studio 2019, and installing the NPM Packages it says you can also just add/create the list of dependencies in to the package.json file.

The dependencies to add are as follows (you can cut & paste it in):-
  "dependencies": {
    "express": "^4.17.1",
    "path": "^0.12.7",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "ts-loader": "^9.2.5",
    "typescript": "^4.3.5",
    "webpack": "^5.51.1",
    "webpack-cli": "^4.8.0"
  }
So a package.json file may look like this...

{
  "name": "jamming",
  "version": "0.0.0",
  "description": "Jamming",
  "main": "server.js",
  "author": {
    "name": ""
  },
  "dependencies": {
    "express": "^4.17.1",
    "path": "^0.12.7",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "ts-loader": "^9.2.5",
    "typescript": "^4.3.5",
    "webpack": "^5.51.1",
    "webpack-cli": "^4.8.0"
  }
}

The name of the project that this was taken from was called Jamming

Set-up Environment

In order to learn and test React, you should set up a React Environment on your computer.
The create-react-app is an officially supported way to create React applications.

If you have NPM and Node.js installed, you can create a React application by first installing the create-react-app.

Install create-react-app by running this command in your terminal:

D:\YourDirectoryToWorkFrom npm install -g create-react-app

When done you can create a React application (named myTestReact)...

D:\YourDirectoryToWorkFrom npx create-react-app mytestreact
It does not like CAPITAL letters in the name (mytestreact NOT MyTestReact).

Then you can log into the folder mytestreact
cd mytestreact

Then to start the React application for your mytestreact do this...

D:\YourDirectoryToWorkFrom npm start
It will open a tab in your browser (it may take a moment)

screen image

The above will result in a new directory inside your chosen directory, eg...
D:\YourDirectoryToWorkFrom\mytestreact\src

I created this in my d:\ReactDirectories\CreateReactApp directory.

Top

subclasses:

We use components to tell React what we want to see on the screen.
When our data changes, React will efficiently update and re-render our components.


Here is an example to start with...

class ShoppingList extends React.Component {
  render() {
    return (
      <div className="shopping-list">
        <h1>Shopping List for {this.props.name}</h1>
        <ul>
          <li>Instagram</li>
          <li>WhatsApp</li>
          <li>Oculus</li>
        </ul>
      </div>
    );
  }
}

// Example usage: <ShoppingList name="Mark" />
Here, ShoppingList is a React component class, or React component type.
A component takes in parameters, called props (short for “properties”), and returns a hierarchy of views to display via the render method.

The render method returns a description of what you want to see on the screen.
React takes the description and displays the result.
In particular, render returns a React element, which is a lightweight description of what to render.
Most React developers use a special syntax called "JSX" which makes these structures easier to write.
The <div> syntax is transformed at build time to React.createElement('div').

The example above is equivalent to (the non JSX version) of:

return React.createElement(
        'div', 
        {className: 'shopping-list'},
    React.createElement('h1', /* ... h1 children ... */),
    React.createElement('ul', /* ... ul children ... */)
);
JSX comes with the full power of JavaScript.
You can put any JavaScript expressions within braces inside JSX.
Each React element is a JavaScript object that you can store in a variable or pass around in your program.

The ShoppingList component above only renders built-in DOM components like <div>, <ul> and <li> .
But you can compose and render custom React components too.
For example, we can now refer to the whole shopping list by writing <ShoppingList>.
Each React component is encapsulated and can operate independently; this allows you to build complex UIs from simple components.

Creating a new React App

See 'Creating a New React App' document by reactjs.org Here

Create React App is a comfortable environment for learning React, and is the best way to start building a new single-page application in React.

It sets up your development environment so that you can use the latest JavaScript features, provides a nice developer experience, and optimizes your app for production.
You’ll need to have Node >= 10.16 and npm >= 5.6 on your machine.

To create a project, run (in Windows Command Prompt):

First log into the directory you want to use
The below will create a new directory there called my-app

npx create-react-app my-app
Say 'y' to install - it may take a few minutes
cd my-app
npm start


Some commands to use from the command propmpt:-

npm start
Starts the development server.

npm run build
Bundles the app into static files for production

npm test
Starts the test runner.

run eject
Removes this tool and copies build dependencies, configuration files and scripts into the app directory (you cannot go back if you run this).

Top

Examples

The examples given in the next pane(s) are taken from a Tic Tac Toe (Noughts and Crosses) program.

It is basically a 3 x 3 grid...

grid

Examples...

class Square extends React.Component {
  render() {
    return (
        <button className="square">

        {/*Tells it to render the .sqPos property value
        - which prints a number in one of the squares.
        In other words it makes the text of the button be 
        the value of sqPos*/} 
        {this.props.sqPos} 

      </button>
    );
  }
}

class Board extends React.Component {
  renderSquare(i) {

    {/*Let's create/set a property for Square class
    - giving it a value (i) which will end up in the grid*/}
    return <Square sqPos={i} />;

  }

So when the routine has been called properly the end result would look like

grid2

Top

Adding onClick to a button

class Square extends React.Component {
  render() {
    return (
            <button className="square" 
            onClick={function() { alert('click'); }}>
        {this.props.sqPos}
      </button>
    );
  }
}
Or you could use the arrow function (=>)command instead, which is probably the preferred way...

class Square extends React.Component {
  render() {
    return (
            <button className="square" 
            onClick={() => { alert('click'); }}>
        {this.props.sqPos}
      </button>
    );
  }
}

Now you can click on a square (it's really a button) and you will get the alert() message on screen.



Top

Adding a constructor

As a next step, we want the Square component to “remember” that it got clicked, and fill it with an “X” mark.
To “remember” things, components use state.

See w3Schools comments on state

React components has a built-in state object.
The state object is where you store property values that belongs to the component.
When the state object changes, the component re-renders.
The state object is initialized in the constructor.
The state object can contain as many properties as you like, eg...
this.state = {
   brand: "Ford",
   model: "Mustang",
   colour: "Red"
};


Let’s store the current value of the Square in this.state, and change it when the Square is clicked.

First we need to add a constructor to the class to initialize the state:

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

  render() {
    return (
                <button className="square" 
            onClick={() => { alert('click'); }}>
        {this.props.sqPos}
      </button>
    );
  }
}
Note...Setting sqPos: null in the constructor will make all the squares display NULL (blank)...
if I still wanted the numbers displayed then I could make it...
this.state = {
   sqPos: this.props.sqPos
};

because in the class 'board' (in a different pane above) I have set a value for sqPos...later, though, it will change so this.props.sqPos will no longer work.


Note...In JavaScript classes, you need to always call super when defining the constructor of a subclass.
All React component classes that have a constructor should start with a super(props) call.

Props are arguments passed into React Components.
See w3Schools page regarding React Props.

See next pane to continue...

Continued...

After setting up the constructor to set the sqPos value to null we then need to change the render method to change the value when the button is clicked.
For now I will change it to show an 'X' in the square that was clicked on.

To do this the onClick function (in the 'class square's render section) needs to be changed to read...

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

render() {
    return (
      <button
        className="square"
        onClick={() => this.setState({sqPos: 'X'})}
      >
        {this.state.sqPos}
      </button>
    );
  } 
}
The this.setState() method is used to change a properties value held in this.state

When a value in the state object changes, the component will re-render, meaning that the output will change according to the new value(s).

Therefore, when we click on a square we are changing the value from NULL to X
The component will then re-render and change the output.




React Developer Tools for Chrome

The React Devtools extension for Chrome lets you inspect a React component tree with your browser’s developer tools.
Click Here for download instructions.

Top

Lifting State Up (pt 1)

Next, to have a complete game, we now need to alternate placing “X”s and “O”s on the board, and we need a way to determine a winner.

Currently, each Square component maintains the game’s state.
To check for a winner, we’ll maintain the value of each of the 9 squares in one location.

We may think that Board should just ask each Square for the Square’s state.
Although this approach is possible in React, we discourage it because the code becomes difficult to understand, susceptible to bugs, and hard to refactor.
Instead, the best approach is to store the game’s state in the parent Board component instead of in each Square.
The Board component can tell each Square what to display by passing a prop, just like we did when we passed a number to each Square.

To collect data from multiple children, or to have two child components communicate with each other, you need to declare the shared state in their parent component instead.
The parent component can pass the state back down to the children by using props; this keeps the child components in sync with each other and with the parent component.


Lifting State Up (pt 2)

We need to add a constructor to the parent (board class) and tell it we need a property (called squares which will hold an array of 9 items (as the board is 9 squares).
We will Null fill it as we want to start with a blank board.

class Board extends React.Component {
                constructor(props) {
    super(props);
    this.state = {
      squares: Array().fill(null),
    };
  }
  renderSquare(i) {
    return <Square sqPos={i} />;
  }

  render() {
    ...more code continues here..
As we start to play the game the array, referred to as this.state.squares, could look like, for example...
"O", null, "X", "X", "X", "O", "O", null, null

it makes better sense to picture it more like...
"O", null, "X"
"X", "X", "O"
"O", null, null


As a Tic Tac Toe board is a 3 x 3 square.

Top

Lifting State Up (pt 3)

And then we have to change the renderSquare method to use the array, as in...

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


Next, we need to change what happens when a Square is clicked.
The Board component now maintains which squares are filled.
We need to create a way for the Square to update the Board’s state.
Since state is considered to be private to the component that defines it, we cannot update the Board’s state directly from Square.

Instead, we’ll pass down a function from the Board to the Square, and we’ll have Square call that function when a square is clicked.

We’ll change the renderSquare method in Board to do this first...

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


So it will set the value of sqPos to be the current state of this.state.squares[i]
then it will pass down the function that will get called when a square is clicked.

NOTE...
Now we’re passing down two props from Board to Square: sqPos and onClick.
The onClick prop is a function that Square can call when clicked.

The actual function (handleClick) needs to be created inside Board, below the constructor, and will look like this...

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

...the function creates a variable called squares and sets it's value to be equal to the array "this.state.squares" - not sure if I need the .slice() but the lesson wants it.
...It then sets the relevant array item in the local squares variable to 'X'.
...Then sets the squares property in this.state
And because now we do not want Square to keep track of the game's state (it's to be handled in Board instead) the constructor in Square is no longer needed...and we should render the values by using this.props.sqPos instead of this.state.sqPos
As well as passing it the function from Boards.

Part 4

The code so far looks like this...

class Square extends React.Component {
  render() {
    return (
        <button className="square"
            onClick={() => this.props.onClick()}
        >
        {this.props.sqPos}
        </button>
    );
  }
}

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

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

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

  render() {
    ....more code below...

Note...
in handleClick, we call .slice() to create a copy of the squares array to modify instead of modifying the existing array.
.slice() without any start/end values (eg .slice(0, 3)) means it will copy everything...(0,3) means it will copy 3 items starting at position 0 (items 0, 1 & 2) only

Top

Function Components

In React, function components are a simpler way to write components that only contain a render method and don’t have their own state.
Instead of defining a class which extends React.Component, we can write a function that takes props as input and returns what should be rendered.
Function components are less tedious to write than classes, and many components can be expressed this way.

So we can replace the Square class with this Square function...

function Square(props) {
   return (
      <button
            className="square"
            onClick={props.onClick}>
         {props.sqPos}
      </button>
   );
}


Note As props is now a parameter of the function we do not refer to it as this.props. Instead we would be passing this.props when we call the function.

Player - X or O

So far we are always putting "X" on the board when a square is clicked.
So we need to add code to alternate between "X" and "O" to allow for 2 players.

To do this we are going to add a new property (xIsNext)) to the Board set up
So inside the Board Class where it sets the state we need it to look like...
this.state = {
   squares: Array(9).fill(null),
   xIsNext: true,
};


And then in the handleClick() function (still in the Board class) we need to check the new property (xIsNext) to see if we need to display "X" or "O".
Then change the value of xIsNext so the next click will display correctly.

handleClick(i) {
   const squares = this.state.squares.slice();
   squares[i] = this.state.xIsNext ? 'X' : 'O';
   this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
   });
}


The line of code xIsNext: !this.state.xIsNext will change the value of xIsNext to be true if it is false and vice-versa.

Top

Too much

Not wanting to put everything in the overview I'm going to stop there.
The whole code for the game can be seen in...

React/ticTacToe.html
React/ticTacToe.js


Top