DEV Community

Cover image for Learning React: Creating a Roll a Dice App - R1
IVEWOR
IVEWOR

Posted on

Learning React: Creating a Roll a Dice App - R1

It's not too late to learn react so, here is my journey. I will try to post everyday about the progress I made. I tried to learn react last year but was not able to finish it and now I'm again a noob.

So, this is my 2nd shot in learning react. Haven't touched the basics of it but instead I will try to learn it by building some projects.

The first project I build is Roll a Dice. This is a very simple one and gave a good idea of how the file structure works and everything to the base level in react. Also, I'm using next.js to build this small web application. I just want to be comfortable with both of these things at the same time that's why.

What I learn

  • React.js and Next.js file structure
  • Running and creating a react application
  • Some jsx
  • HTML and CSS in react
  • useState Hook
  • and other basic stuff

Now, let's build.

Roll a Dice Web App in React.js and Next.js

Create repo

This is not necessary but it's an good idea to keep everything in Github repo for various needs. But mine is to have some commits everyday on my profile and learn every system that I need to accomplish in real world job.

I just then cloned that repo in my system. Opened the terminal, cd into project directory.

Creating the project

Since, I'm using Next.js so, the command to create the project will be:

npx create-next-app@latest .

. in the end so, it won't create another directory in the project project folder and take base directory name as it is.

You can then select your preferred configuration like JS or TS. I'm using JS, for tailwind say no. Since it's a very small project we don't need that.

After completion of the installation. Run the command to test if it's working.

npm run dev

Visit localhost:3000, you should see the vercel/next.js landing page.

If upto this point if everything is working fine. Congratulations, we have now learned how to create a react project using next.js.

Clean up the files

The next step is to clean some files and remove the unwanted code from our project.

You can read about the project structure here, I won't talk about this here.

Remove everything except the page.js and layout.js from the src/app directory.

layout.js

The default code should look like this:

import { Inter } from "next/font/google";
import "./globals.css";

const inter = Inter({ subsets: ["latin"] });

export const metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  );
}

Enter fullscreen mode Exit fullscreen mode

We're going to remove some of it and keep and add what we need for this project.

Remove the second import of CSS or just rename it to style.css. We can keep the fonts. Next we have export metadata. We're going to change it instead of removing to

export const metadata = {
  title: "Roll a Dice",
  description: "A simple roll a dice web app!",
};
Enter fullscreen mode Exit fullscreen mode

Next keep the remaining Root function. The end code of the file should look like this:

import { Inter } from "next/font/google";
import "./style.css";

const inter = Inter({ subsets: ["latin"] });

export const metadata = {
  title: "Roll a Dice",
  description: "A simple roll a dice web app!",
};

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  );
}
Enter fullscreen mode Exit fullscreen mode

Next, create a style.css file under the same directory src/app, because we need one style file and we imported it on the top of layout.js file.

page.js

In this file, let's remove everything and write from the beginning. Let's first have a function to render our homepage with a simple heading text.

export default function Home() {
  return (
    <main className="page">
      <h1>Roll a Dice</h1>
    </main>
  );
}
Enter fullscreen mode Exit fullscreen mode

In this code, we have a simple react function which returns a simple h1 in our application.

Next, we need the dice image and a button to roll it. We want the image to randomly change to another one upon clicking that button.

Images

Before that let's collect some images for the dice. I have already downloaded them from the web. So, you can copy these 6 images from the repo. Store them in the public folder. Make sure it is present in the root directory, same level as src directory.

- roll-dice
-- src/app
-- public/all-your-images.png
Enter fullscreen mode Exit fullscreen mode

Make sure the dice images are named like this:

dice-1.png
dice-2.png
...
dice-6.png
Enter fullscreen mode Exit fullscreen mode

You can name it whatever you want just please adjust it accordingly in the code.

page.js

Now, let's create an image and the button, which we talked earlier. For the image we need to import the Image component from next.js since we're using next.js.

import Image from "next/image";

export default function Home() {
  return (
    <main className="page">
      <div className="img-side">
        <Image src="/dice-1.png" width="400" height="400" />
      </div>

      <div className={"text-side"}>
        <h1>Roll a Dice</h1>
        <p>
          Roll a Dice is a user-friendly web app that simulates dice rolls.
          Perfect for games or decision-making, it offers quick, random results
          with a single click.
        </p>
        <button>Roll the dice</button>
      </div>
    </main>
  );
}
Enter fullscreen mode Exit fullscreen mode

Now, our web app looks like this:

Image description

style.css

Let's add some styling to it. I won't talk about this much. Here's the CSS:

body {
  background-color: #f0f0f0;
  padding: 10px;
}

body,
* {
  margin: 0;
}

.page {
  max-width: 850px;
  padding: 20px;
  margin: 0 auto;
  background-color: #fff;
  border-radius: 28px;
  display: grid;
  gap: 20px;
  align-items: center;
}

.img-side img {
  width: 350px;
  height: auto;
  max-width: 100%;
}

.text-side h1 {
  margin-bottom: 10px;
}

.text-side button {
  padding: 12px 28px;
  line-height: 1;
  border: solid 2px #222;
  background-color: #222;
  color: #fff;
  font-size: 17px;
  letter-spacing: 0.5px;
  border-radius: 18px;
  margin-top: 30px;
  cursor: pointer;
  transition: cubic-bezier(0.6, -0.28, 0.735, 0.045) 0.2s all;
}

.text-side button:hover {
  opacity: 0.9;
}

@media (min-width: 850px) {
  .page {
    grid-template-columns: 1fr 1fr;
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, the web app looks like this:

Image description

Adding the functionality

Again in page.js, we're going to import a useState which an react hook using import { useState } from "react";. First let's do the destructuring and initialize the variable with 1.

import Image from "next/image";
import { useState } from "react";

export default function Home() {

const [num, setNum] = useState(1);
Enter fullscreen mode Exit fullscreen mode

Then we're going to create random number generator function inside our Home function, which is going to return a number from 1 to 6.

import Image from "next/image";
import { useState } from "react";

export default function Home() {

  const [num, setNum] = useState(1);

  const randomNumberInRange = (min, max) => {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }


....rest of the code
Enter fullscreen mode Exit fullscreen mode

Now, we need a function that fires our randomNumberInRange function.

import Image from "next/image";
import { useState } from "react";

export default function Home() {
  const [num, setNum] = useState(1);

  const randomNumberInRange = (min, max) => {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  };

  const handleClick = () => {
    setNum(randomNumberInRange(1, 6));
  };

  return (

....rest of the code
Enter fullscreen mode Exit fullscreen mode

Now, we have to assign the handleClick function to the button. So, it works on click. Let's do that:

<button onClick={handleClick}>Roll the dice</button>
Enter fullscreen mode Exit fullscreen mode

We're mostly done with our web app. We just need to make some adjustments in the Image tag so, it can use the random num from our function. To do that, modify the Image src to <Image src={"/dice-" + num + ".png"} width="400" height="400" />.

Now, the page.js code should look like this:

"use client";

import Image from "next/image";
import { useState } from "react";

export default function Home() {
  const [num, setNum] = useState(1);

  const randomNumberInRange = (min, max) => {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  };

  const handleClick = () => {
    setNum(randomNumberInRange(1, 6));
  };

  return (
    <main className="page">
      <div className="img-side">
        <Image src={"/dice-" + num + ".png"} width="400" height="400" />
      </div>

      <div className={"text-side"}>
        <h1>Roll a Dice</h1>
        <p>
          Roll a Dice is a user-friendly web app that simulates dice rolls.
          Perfect for games or decision-making, it offers quick, random results
          with a single click.
        </p>
        <button onClick={handleClick}>Roll the dice</button>
      </div>
    </main>
  );
}
Enter fullscreen mode Exit fullscreen mode

Now, if you click on the button. The image should start changing like rolling a dice.

And that's it for this web app, atleast for now.

If you have any suggestions or feedback, then please share! The repo is here

Top comments (0)