In the previous lessons we started with a simple Pixel component, we grouped up 900 Pixel components in a Canvas component, and we used 4 Pixel components in a ColorPicker component.

We made it possible to color Pixels, and to have a set of colors to choose from. We also set a default color.

Now let’s add the last bit of functionality: we want to color pixels in the canvas, with the color selected in the ColorPicker.


When I click a pixel, that’s going to transform its background color to the currently active color in the color picker.

The Pixel component already has an onClick handler, because we added it when we wanted to change the default color in the ColorPicker. Luckily this is just calling the parent prop, so we can pass our handler in the Canvas component:

//...
const Canvas = props => {
  //...

  const changeColor = (rowIndex, colIndex) => {
    //...
  }

  return (
    <div className={'canvas'}>
      {matrix.map((row, rowIndex) =>
        row.map((_, colIndex) => {
          return (
            <Pixel
              key={`${rowIndex}-${colIndex}`}
              background={Colors[matrix[rowIndex][colIndex]]}
              onClick={e => changeColor(rowIndex, colIndex)}
            />
          )
        })
      )}
    </div>
  )
}

The changeColor() method is what actually changes the color of a pixel. It’s in the Canvas component because that’s where the state of the whole set of pixels (the matrix variable) is kept.

Let’s implement it.

We clone the matrix nested array, by using this kind of strange way: JSON.parse(JSON.stringify(my_array)) so that we don’t go and change the previous array, but we create a new one. Why we do so? For immutability reasons. We can’t change the matrix implicitly by editing its current value, but we want it to only change through our setMatrix() call.

After cloning the matrix we then update the specific location given by rowIndex and colIndex and we set it to the new color, and after this we set the new state:

const changeColor = (rowIndex, colIndex) => {
  const newMatrix = JSON.parse(JSON.stringify(matrix))
  newMatrix[rowIndex][colIndex] = props.currentColor
  setMatrix(newMatrix)
}

currentColor is passed by the App component when it includes Canvas, like it already does for ColorPicker:

function App() {
  const [color, setColor] = useState(0)

  return (
    <div className="App">
      <ColorPicker currentColor={color} setColor={color => setColor(color)} />
      <Canvas currentColor={color} />
    </div>
  )
}

We are done!

Here is the result:

The end result

And here is the full app in CodeSandbox for you to try out if you missed a step: https://codesandbox.io/s/7wq3pqv9oq

Wrapping up

We finally finished our little application. We can now start playing it to draw pixel art all day long 😄

. . .

I’m joking. Time to go to the next lesson, to wrap up the module!


Go to the next lesson