Course: Section

Get Started with Modern React: Learn by Doing

Episode: Title

S03・V11: Passing Functions

Date Created: July 17th, 2019
Last Updated: 27 days ago

Objective
  • We will show how a child component can communicate with, and update, its parent.
Watch Video
Duration: 3m 54s

Passing Functions

We need to be able to change the displayed value when a Square is clicked. The Board component currently 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 the Square call that function when a Square is clicked. This is a neat way for the child component to update the data in the parent component.

In the Board, we will define a function that just prints out which Square is clicked. We will arbitrarily call this function: handleClickEvent.

  const [squares, setSquares] = useState(initialSquares);

  const handleClickEvent = i => {    console.log(`Square ${i} clicked`);  };
  const renderSquare = i => {

Now, we’ll change the renderSquare function in the Board. We will pass our handleClickEvent function into a prop which we will call onClickEvent.

  const handleClickEvent = i => {
    console.log(`Square ${i} clicked`);
  }

  const renderSquare = i => {
    return (
      <Square
        value={squares[i]}
        onClickEvent={() => handleClickEvent(i)}      />
    );
  };

Now we can update the button in the Square component to use the passed down onClickEvent function via props, attaching it to the built-in event prop called onClick.

const Square = props => {
  return (
    <button
      className="square"
      onClick={() => props.onClickEvent()}    >
      {props.value}
    </button>
  );
};

Since we have made use of the onClick prop on the button, React will set up a click event listener. In fact, React will set up a separate event listener for each of the 9 square buttons. We can now demonstrate that clicking on the board prints out which square has been clicked to the console.

Open Chrome’s developer tools, and select the “Console” tab. We will click on the square with index 2 first, and we can see it print out. We will click on the square with index 7, and we can see it print out.

Review of Sequence of Events

We will review what’s happening here.

  • The onClick prop on the built-in DOM button component tells React to set up a click event listener.
  • When the button is clicked, React will call the onClick event handler.
  • This event handler calls the onClickEvent function, which is in the props object.
  • The Square’s onClickEvent prop was specified by the Board.
  • Passed in to this prop is a function which calls handleClickEvent with the index of the Square.
  • The handleClickEvent function prints out to console.

Code Snapshot

src/index.js
import React, { useState } from 'react';
import ReactDOM from 'react-dom';

import './index.css';

const Square = props => {
  return (
    <button
      className="square"
      onClick={() => props.onClickEvent()}
    >
      {props.value}
    </button>
  );
};

const Board = () => {
  const initialSquares = [
    null, null, null,
    null, null, null,
    null, null, null,
  ];
  // `squares` is a 9-element array; each element is `X`, `O`, or `null`.
  const [squares, setSquares] = useState(initialSquares);

  const handleClickEvent = i => {
    console.log(`Square ${i} clicked`);
  };

  const renderSquare = i => {
    return (
      <Square
        value={squares[i]}
        onClickEvent={() => handleClickEvent(i)}
      />
    );
  };

  return (
    <div style={{
      backgroundColor: 'skyblue',
      margin: 40,
      padding: 20,
    }}>
      Board
      <div className="board-row">
        {renderSquare(0)}
        {renderSquare(1)}
        {renderSquare(2)}
      </div>
      <div className="board-row">
        {renderSquare(3)}
        {renderSquare(4)}
        {renderSquare(5)}
      </div>
      <div className="board-row">
        {renderSquare(6)}
        {renderSquare(7)}
        {renderSquare(8)}
      </div>
    </div>
  );
};

const Game = () => {
  return (
    <div className="game">
      Game
      <Board />
    </div>
  );
};

ReactDOM.render(
  <Game />,
  document.getElementById('root')
);

Summary

A child can update a parent component by calling a function that the parent passed down to the child via props. We showed this by passing a click handler from the Board down to each Square, which is invoked when the user clicks on a Square.

Next Up…

In the next video, we will set the value of the Square when it is clicked.