Coding Heaven logo

Coding Heaven

Create Movie App with Node.js and React. Part 2

    Category: react
Author's Photo

Author: Vlada

Date: 09/14/2025

Thumbnail for JS article

Node.js"

Hello, devs! Today we continue working on our Movie application, focusing on the frontend part. If you missed the backend setup, you can check out part one of the tutorial. Also, if you need a source code, you can check the repo.


Setting Up a new React app


Now we’re going to start by creating a new React project. I recommend creating a new directory and placing your movie backend folder inside it. Then, inside this newly created parent folder, we’ll run the command to create a React app.


npx create-react-app my-app

So my folder structure looks like this now:

movie folder structure
To run your front-end app, you can use the command:

npm start

You should see the default React app if you go to localhost:3000:


movie folder structure
Now that everything is up and running, we can start creating our Movie App container. Let’s update our App.js and index.js files.

import './App.css';
function App() {
  return (
    <div className="App">
    </div>
  );
}
export default App;

index.js is our app’s entry point, and we just need to clean it up. App.js will be our main component that displays the movies.

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

👉 App.css - I removed all css rules from the file, we are going to write our own
👉 reportWebVitals.js - We can remove the file.
👉 index.css - Keep it as it is. This is pur global app styles.
👉 setupTests.js - We are not goint to use it.
👉 App.test - We don’t need it this time.


Display movies data in App.js


Our main work will be in App.js, as I mentioned earlier. This will be a component, that is responsible for fetching movie data from our backend and displaying the results on the page. App.css will be used to apply styles specifically to this App component.


Let's update our App.js:


import './App.css';
import { useState } from 'react';

function App() {

  const [movies, setMovies] = useState([]); // react hook to manage state

  const fetchMovies = async () => {
    const response = await fetch('http://localhost:3001/getMovies'); /
    const data = await response.json();
    setMovies(data.results);
  }

  useEffect(() => {
    fetchMovies();
  }, []); 


  return ( //  Everything inside the return will be displayed on the page
    <div className="App">
      <h1>Popular Movies</h1>
        <ul>
          {movies.map(movie => ( /*This is how we map our results to element in the list*/
            <li key={movie.id}>{movie.title}</li>
          ))}
        </ul>
    </div>
  );
}

Let’s review our code:


👉 const [movies, setMovies] This is one of the React hooks. We use it to manipulate the state of certain values. When we receive new data from our server, we assign it to this state instead of leaving it empty.
movies – the variable that stores the values.
setMovies – the function used to update the value.

👉 await fetch(‘http:// localhost:3001/getMovies’) . Here we are making request to our server, that we created in the previous post. We use JavaScript Fetch API for that.

👉 setMovies(data.results) this is how we reassign our movies state, and now this movie variable contains list of moves
👉 useEffect - this is another React hook that runs a side effect. In our case, it runs as soon as the App.js component appears on the page and makes a call to our server.

We’re almost done, but there’s one last thing we need to take care of. Right now, our request is being blocked by CORS. This is a browser security feature that prevents web clients sending requests to different domains.

To fix this, we need to update the index.js file in our movie backend and add CORS support. So, let’s navigate to the movie app folder and install the cors package.


// index.js in movies backend

const express = require('express')
require('dotenv').config()
const app = express()
const port = 3001

var cors = require('cors')
app.use(cors())

// keep the rest of the code unchanged

Now let’s visitlocalhost:3000 and see the result

first result no styles

Awesome, we got our data! Now let’s add some differentiation. I want to display posters for each movie, rating and release date. And also make a separate section for movies that have rating higher than 7.

function App() {
  const [popularMovies, setPopularMovies] = useState([]);
  const [highlyRated, sethighlyRatedMovies] = useState([]);

  const fetchMovies = async () => {
    const response = await fetch("http://localhost:3001/getMovies");
    const data = await response.json();
    const results = data.results;

    const popMovies = results.filter((movie) => movie.popularity > 400);
    const highlyRatedMovies = results.filter((movie) => movie.vote_average > 7);
    
    setPopularMovies(popMovies);
    sethighlyRatedMovies(highlyRatedMovies);
  };

  useEffect(() => {
    fetchMovies();
  }, []);

  return (
    <div className="App">
      <section>
        <h3>Popular Movies</h3>
        <ul>
          {popularMovies.map((movie) => (
            <li key={movie.id}>
              {movie.title}
              <span>Released: {movie.release_date}</span>
              <img
                src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
                alt={movie.title}
              />
              <span>Rating: {movie.vote_average}</span>
            </li>
          ))}
        </ul>
      </section>
            <section>
        <h3>Highly Movies</h3>
        <ul>
          {highlyRated.map((movie) => (
            <li key={movie.id}>
              {movie.title}
              <span>Released: {movie.release_date}</span>
              <img
                src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
                alt={movie.title}
              />
              <span>Rating: {
              movie.vote_average 
              
              } ⭐</span>
            </li>
          ))}
        </ul>
      </section>
    </div>
  );
}

At this point, we are done with our compoentn, and now we can add styles.

Add Styles to our movies


Update index.css to add a nice background.

/*index.css front-end*/

body {
  /*Add these 3 lines to previous code. This will create a nice gradient background*/
  background: #833AB4;
  background: linear-gradient(80deg,rgba(131, 58, 180, 1) 0%, rgb(0, 0, 0) 50%, rgb(67, 3, 92) 100%);
    color: white;
}

Now, it's time to update our index.js and add classes and ids.

// prev code
return (
  <div className="App">
  <section className="movies-section"> 
    <h3>Popular Movies</h3>
    <ul className="movies-list">
      {popularMovies.map((movie) => (
        <li key={movie.id} className="movie-card">
          <img
            src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
            alt={movie.title}
          />
          <div className="movie-info">
            <h4>{movie.title}</h4>
            <span>Released: {movie.release_date}</span>
            <span>Rating: {movie.vote_average} ⭐</span>
          </div>
        </li>
      ))}
    </ul>
  </section>

  <section className="movies-section">
    <h3>Highly Rated</h3>
    <ul className="movies-list">
      {highlyRated.map((movie) => (
        <li key={movie.id} className="movie-card">
          <img
            src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
            alt={movie.title}
          />
          <div className="movie-info">
            <h4>{movie.title}</h4>
            <span>Released: {movie.release_date}</span>
            <span>Rating: {movie.vote_average} ⭐</span>
          </div>
        </li>
      ))}
    </ul>
  </section>
</div>);

And now add this to App.css

.App {
  min-height: 100vh;
  padding: 2rem;
  background: linear-gradient(
    80deg,
    rgba(131, 58, 180, 1) 0%,
    rgb(0, 0, 0) 50%,
    rgb(67, 3, 92) 100%
  );
  color: #fff;
  font-family: Arial, Helvetica, sans-serif;
}

.movies-section {
  margin-bottom: 3rem;
}

.movies-section h3 {
  font-size: 1.8rem;
  margin-bottom: 1rem;
  border-left: 4px solid #ffdd57;
  padding-left: 0.5rem;
}

.movies-list {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 1.5rem;
  padding: 0;
  margin: 0;
}

.movie-card {
  background: rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  overflow: hidden;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.movie-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 6px 15px rgba(0, 0, 0, 0.5);
}

.movie-card img {
  width: 100%;
  height: auto;
  display: block;
}

.movie-info {
  padding: 0.8rem;
}

.movie-info h4 {
  font-size: 1rem;
  margin-bottom: 0.4rem;
}

.movie-info span {
  display: block;
  font-size: 0.85rem;
  color: #ddd;
  margin-bottom: 0.2rem;
}

And let's check out the final result:


final result

I think it looks pretty good, you also can go ahead to play around and add new things and feature.

Thank you for building the project with me I will see you in the next article.
Happy Coding!