Advanced JavaScript Concepts
Tags: throttle, javascript, webdev, tutorial
Published: 2022-07-27 01:26:00

I was sitting behind my computer thinking of creating a small application that would leverage some advanced JavaScript concepts.. in particular I was thinking of real world implementations of `throttle` and `debounce`.

I've created an application that kind of leverages the logic of `throttle` but will also showcase some difficult to maneuver web api's such as `setTimeout` and `setInterval` 

if this has piqued your interest.. please read on.

##TLDR

for those of you that don't like to read.. here is the logic for the application

```jsx
const GetScores = () => {
  const [homeScore, setHomeScore] = useState(0);
  const [awayScore, setAwayScore] = useState(0);

  const updateScore = () => {
    const scoreOptions = [0, 2, 3];
    const randomNum = () => Math.floor(Math.random() * 3);

    setHomeScore(homeScore + scoreOptions[randomNum()]);
    setAwayScore(awayScore + scoreOptions[randomNum()]);
  };

  return {
    homeScore,
    awayScore,
    updateScore,
  };
};



const usePlayGame = ({ 
  team1 = "https://cdn.mos.cms.futurecdn.net/8227s5kMEx84YEHWLbxCb4-1200-80.jpg",
  team2 = "https://www.dailynews.com/wp-content/uploads/migration/2015/201506/SPORTS_150619439_AR_0_FHMRLLUSDJPX.jpg?w=1024",
  timeLapse,
  delay,
}) => {
  const [time, setTime] = useState(15);
  const [pause, setPause] = useState(false);
  const [quarter, setQuarter] = useState(0);
  const [winner, setWinner] = useState("");

  const { updateScore, homeScore, awayScore, homeTeam, awayTeam } = GetScores(
    team1,
    team2
  );

  useEffect(() => {
    // if we have finished the last quarter
    if (quarter >= 3) {
      // we decide the winner by checking the scores
      const winner = homeScore > awayScore ? homeTeam : awayTeam;
      //   we set the winner
      setWinner(winner);
      //   we pause the game indefinitely
      return setPause(true);
    }
    // Let's unpause after a break (setTimeout callback)
    if (pause) {
      setPause(false);
    }

    // on every interval increase time by the timelapse set (default 1000 ms)
    const interval = setInterval(() => {
      updateScore();
      setTime(time - 1);
    }, timeLapse);

    // if the time is run out and the game is not yet over
    if (time === 0 && quarter !== 3) {
      // We pause the match
      setPause(true);
      //   we move to the next quarter
      setQuarter(quarter + 1);
      //   we reset the time after a short break (delay default 5000 ms)
      setTimeout(() => {
        setTime(time + 15);
      }, delay);
      return clearInterval(interval);
    }
    return () => clearInterval(interval);
  }, [time]);

  return {
    time,
    pause,
    quarter,
    winner,
    homeScore,
    awayScore,
    homeTeam,
    awayTeam,
  };
};

```

##Fantasy Basketball
for the implementation of the logic I wanted to create something fun. Something that I've started enjoying a lot... Basketball. Go Warriors!! am I right.

I have decided to create a fantasy basketball application that can run an entire game as soon as the page loads. There are a lot of moving parts to this application, but not to worry. we will build out every piece individually. The following we will need:

- a timer
- a scoreboard
- breaks after every quarter
- deciding a winner

### Prerequisites

This tutorial will be build in React with JavaScript, a basic understanding of both would definitely come in handy for this tutorial just to understand some of the more complex pieces of the application.

we will be installing one more dependency.. styled components.

`npm install --save-dev styled-components`

not a necessity, just very powerful in my opinion and comes in handy in almost every project. It is a library to turn your css into React components where you can also pass along properties to it to manipulate the css.

### Getting started
to get started with any react project for home use, we can simple use Create React App (CRA). Create React app is a powerful tool to bootstrap a React project and the perfect solution for building simple applications like this.

Run the following command to get started.

`npx create-react-app ${your app name here}`

then type the following command into your CLI `cd ${your app name here}` and voila. we have a project setup.


### Structure
Below you can see the structure of the game.
I will be going over every component as we move along.

![Structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ph26dk0fiecwptxlnay5.png)
 
Recreate the structure as you see fit, if you want to follow along with me then recreate the folders as shown in the image above

### API
the first component I would like to build is the API. In this tutorial I'm not actually using an API, I have just created a hook that runs locally but basically mocks an API call.


this logic is stored in src/Services/api.js

first let's start with what we want this API to return.
We want the following:
- Home team score
- Away team score
- function to update the score


```jsx
import { useState } from "react";

export const GetScores = (
) => {
  const [homeScore, setHomeScore] = useState(0);
  const [awayScore, setAwayScore] = useState(0);
  
const updateScore = () => {
    const scoreOptions = [0, 2, 3];
    const randomNum = () => Math.floor(Math.random() * 3);

    setHomeScore(homeScore + scoreOptions[randomNum()]);
    setAwayScore(awayScore + scoreOptions[randomNum()]);
  };

  return {
    homeScore,
    awayScore,
    updateScore,
  };
};

```

to keep track of the scores I created to state variables that can keep track of each teams scores independently.

Next I needed a function that would update the score whenever we needed it to. The `updateScore` function does just that. Every second we run the play, the `updateScore` function runs on each of the teams.

I've created an array with the possible scores in a basketball game being: 0, 2 and 3. You can dunk, layup or shoot to get 2 points and you can shoot from the 3 point line to get 3 points, your only other option is missing.

I then needed something to determine which one of the three options it would be. I created a function that returns `Math.floor(Math.random()*3)`. Let's break that down. 

Math.floor takes out decimal values and "floors" them so brings it basically removes the decimals (e.g. 10.8 is 10)

Math.random will give us a random numerical value between 0 and 1 (e.g 0.245 or 0.678) we multiply this with the amount of options we have (3) and we will receive a random number between 0 and 2 which corresponds with the indexes in our array.

then we set the new score by adding up the old score with the randomly selected outcome and return those.

### Hooks
Now it is time to get to the nitty gritty. I've created a custom hook to take care of all the logic pertaining to the actual game. This way I keep my UI component clean of too much logic and make it easier to read.

this logic is stored in src/Services/hooks.js

```jsx

import { useState, useEffect } from "react";
import { GetScores } from "./api";

const usePlayGame = ({ team1, team2, timeLapse = 1000, delay = 5000 }) => {
  const [time, setTime] = useState(15);
  const [pause, setPause] = useState(false);
  const [quarter, setQuarter] = useState(0);
  const [winner, setWinner] = useState("");

  const { updateScore, homeScore, awayScore } = GetScores();

  useEffect(() => {
    // if we have finished the last quarter
    if (quarter >= 3) {
      // we decide the winner by checking the scores
      const winner = homeScore > awayScore ? team1 : team2;
      //   we set the winner
      setWinner(winner);
      //   we pause the game indefinitely
      return setPause(true);
    }
    // Let's unpause after a break (setTimeout callback)
    if (pause) {
      setPause(false);
    }

    // on every interval increase time by the timelapse set (default 1000 ms)
    const interval = setInterval(() => {
      updateScore();
      setTime(time - 1);
    }, timeLapse);

    // if the time is run out and the game is not yet over
    if (time === 0 && quarter !== 3) {
      // We pause the match
      setPause(true);
      //   we move to the next quarter
      setQuarter(quarter + 1);
      //   we reset the time after a short break (delay default 5000 ms)
      setTimeout(() => {
        setTime(time + 15);
      }, delay);
      return clearInterval(interval);
    }
    return () => clearInterval(interval);
  }, [time]);

  return {
    time,
    pause,
    quarter,
    winner,
    homeScore,
    awayScore,
  };
};

export default usePlayGame;
```

Let me break this badboy down. Let's start with the `useEffect` and I'll break down what each part of the hook will do.

```jsx


    // if we have finished the last quarter
if (quarter >= 3) {
      // we decide the winner by checking the scores
      const winner = homeScore > awayScore ? team1 : team2;
      //   we set the winner
      setWinner(winner);
      //   we pause the game indefinitely
      return setPause(true);
    }

```

This if statement is basically a principal taken from recursive programming. When we reach the final quarter we want the useEffect to no longer run so we return with `setPause` to true. 


Recursive programming is where we call a function inside of itself and have an exit after we have reached a certain point. 

```jsx
let count = 0;

const addTo10 = () => {
if(count === 10) return

console.log(count)

addTo10(count++)

}
```

as you can see with this simple example, we have a count that starts off at 0. The addTo10 function calls itself with `count++` adding up the count every time it runs. The if statement in the beginning makes sure that when the count equals 10 we return and the function stops running.

you can copy and paste this into a browser to see how it works.

the next code block that is important is this
```jsx
// on every interval increase time by the timelapse set (default 1000 ms)
    const interval = setInterval(() => {
      updateScore();
      setTime(time - 1);
    }, timeLapse);

```

we create a timer by using `setInterval` which reruns a function after every interval. The `timeLapse` variable is set to 1000ms in the above example which accounts for a single second. so we decrease a number value by 1 every time it runs. This is our clock.

on the interval we update the score which is the function we get from our API we created before:

```jsx

  const { updateScore, homeScore, awayScore } = GetScores();
```

this will update the score and export the homeScore and awayScore for the respective teams.


```jsx
 // if the time is run out and the game is not yet over
    if (time === 0 && quarter !== 3) {
      // We pause the match
      setPause(true);
      //   we move to the next quarter
      setQuarter(quarter + 1);
      //   we reset the time after a short break (delay default 5000 ms)
      setTimeout(() => {
        setTime(time + 15);
      }, delay);
      return clearInterval(interval);
    }
    return () => clearInterval(interval);
  }, [time]);

```


this is the main code. Let's go through it step by step. if the time hits zero and it isn't the final quarter we want to set pause to true, increase the quarter and use a `setTimeout` callback to reset the timer back to 15 and use a `delay` variable to set the milliseconds we want to wait (default 5000 ms or 5 sec). within useEffect we will have to return the clearInterval to stop the intervals from running. 

after this has run we will have to `setPause` to false to continue our loop

```jsx
if(pause){
setPause(false)
}
```

### Throttle
if you look up the principle of throttle in JavaScript it is usually has similar code as the one above. we want to set a variable or state to true so a function can run, inside the function we set the state to false to make it stop running and use a `setTimeout` to start the function again. In this case `setInterval` is taking care of resetting the state. 

below you can see an example of throttling in JavaScript

```jsx
//initialize throttlePause variable outside throttle function
let throttlePause;
 
const throttle = (callback, time) => {
  //don't run the function if throttlePause is true
  if (throttlePause) return;
 
  //set throttlePause to true after the if condition. This allows the function to be run once
  throttlePause = true;
   
  //setTimeout runs the callback within the specified time
  setTimeout(() => {
    callback();
     
    //throttlePause is set to false once the function has been called, allowing the throttle function to loop
    throttlePause = false;
  }, time);
};

```


### UI
now for the fun part. We can build out the UI. The UI is build out into several components, the main one being `ScoreCard`

```jsx
import React from "react";
import Winner from "../Winner";
import { CardWrapper, Score, Teams, TeamLogo } from "./styles";
import usePlayGame from "../../Services/hooks";
import Time from "../Time";
import Break from "../Break";
import { game } from "./utils";

const ScoreCard = ({
  team1 = "https://cdn.mos.cms.futurecdn.net/8227s5kMEx84YEHWLbxCb4-1200-80.jpg",
  team2 = "https://www.dailynews.com/wp-content/uploads/migration/2015/201506/SPORTS_150619439_AR_0_FHMRLLUSDJPX.jpg?w=1024",
  timeLapse,
  delay,
}) => {
  const { quarter, time, homeScore, awayScore, pause, winner } = usePlayGame({
    team1,
    team2,
    timeLapse,
    delay,
  });

  return (
    <CardWrapper>
      <Teams>
        <TeamLogo src={team1} /> vs
        <TeamLogo src={team2} />
      </Teams>
      {game[quarter]}
      <Score>
        {homeScore} - {awayScore}
      </Score>
      {pause ? <Break quarter={quarter} /> : <Time time={time} />}
      <br />
      {winner && <Winner img={winner} />}
    </CardWrapper>
  );
};

export default ScoreCard;


```

The scorecard has the teams

```jsx
<Teams>
 <TeamLogo src={team1} /> vs
 <TeamLogo src={team2} />
</Teams>
```
the quarter we are in which utilizes a `utils.js` file. I've combined both in the section below

```jsx
{game[quarter]}

export const game = ["First Half", "Second Half", "Third Half", "Full Time"];
```
it selects the correct game by using the quarter which runs from 0 to 3 to decide what part of the game we are in.

the next part is the score
```jsx
<Score>
  {homeScore} - {awayScore}
</Score>
```
which receives the homeScore and awayScore from our `hooks.js` file

then we have a couple of operators that use the `Break`, `Time` and `Winner` components
```jsx
{pause ? <Break quarter={quarter} /> : <Time time={time} />}
<br />
{winner && <Winner img={winner} />}
```
if we are on a pause we want to showcase the word 'break' except for when we reach full time. otherwise we want to showcase the time but because time runs from 15 to 0, we want to showcase it as 15, 14, 13, 12, 11, 10, 09, 08, 07, 06, 05, 04, 03, 02, 01, 00. 

for those reasons I've build out the following components in the `Break` folder and the `Time` folder respectively.

```jsx

//Break
import React from "react";

const Break = ({ quarter }) => {
  console.log(quarter);
  return <div>{quarter < 3 ? "Break" : ""}</div>;
};

export default Break;

//Time
import React from "react";

const Time = ({ time }) => <div>{time < 10 ? `0${time}` : time}</div>;

export default Time;

```

the final piece of the puzzle is the Winner component

```jsx

import React from "react";
import { WinnerCard } from "./styles";

const Winner = ({ img }) => {
  return (
    <div>
      <h1>!! Winner !!</h1>
      <WinnerCard src={img} />
    </div>
  );
};

export default Winner;

```

#### Styled components

for the `ScoreCard` component and the `Winner` component I have created the following styles using styled components:

```jsx
//ScoreCard
import styled from "styled-components";

export const CardWrapper = styled.div`
  display: flex;
  flex-direction: column;
  text-align: center;
`;

export const Score = styled.div`
  display: flex;
  font-size: 8rem;
  justify-content: center;
`;

export const Teams = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 3rem;
  font-weight: bold;
  gap: 1rem;
  padding: 15px;
  border-bottom: 10px double black;
`;

export const TeamLogo = styled.img`
  width: 200px;
  height: 115px;
  border-radius: 15px;
  padding: 10px;
  border: 10px double black;
`;

export const Winner = styled.div`
  display: flex;
  flex-direction: column;
`;

```

```jsx
//Winner

import styled from "styled-components";

export const WinnerCard = styled.img`
  width: 200px;
  height: 115px;
  padding: 10px;
  border: 5px double black;
  border-image: linear-gradient(to top right, #a67c00 10%, #fabf00 90%) 1 round;
`;

```

these you can import into your file with named exports from './styles' like so

```jsx
//ScoreCard
import { CardWrapper, Score, Teams, TeamLogo } from "./styles";

//Winner
import { WinnerCard } from "./styles";
```

### Extra Curricular
for those of you interested in the power of styled components I have added a styled component that I have used on my App.js to set the layout for the page

```jsx

import styled from "styled-components";

export const Direction = styled.div`
  ${({ direction }) => {
    return direction === "row"
      ? `{
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem;
  margin: auto 0;
  overflow: scroll;
  max-width: 100vw;
}`
      : `{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  grid-gap: 1rem;
  overflow: scroll;
}`;
  }}
`;


```

this component takes in a direction, if that direction is 'row' then the first part of the ternary is used on our wrapper component to set all of our child components in a single row. If you decide not to use that but go for 'column' or anything else for that matter instead, the flow will be done in a grid layout that is responsive.

### App.js
Below you will find my implementation of the ScoreCard in our App.js file.

```jsx
import { Direction } from "./styles";
import ScoreCard from "./Components/ScoreCard";

function App() {
  return (
    <Direction direction="row">
      <ScoreCard />
    </Direction>
  );
}

export default App;

```

### Thank You
I hope this helped make sense of `setInterval`, `setTimeout`, throttle and recursion. It was a lot of fun to build and if you guys have questions I would love to hear them from you.

Please leave a like :heart:, leave a comment :page_with_curl: or connect :wave: :

[Github](https://github.com/lucvankerkvoort)
[Linkedin](https://linkedin.com/in/lucvankerkvoort)
[Discord](https://discord.gg/x36bN36w)


Here is a link to the Github Repo: [Sports App](https://github.com/lucvankerkvoort/Sports-App)