React and .NET Core 6.0 Sample Project with Docker - Part 2
Tags: react, javascript
Published: 2022-10-16 16:38:06

This article will explain how to create React Js application and consume ASP.NET Core Web API requests to fetch the movies data.
We will go through step by step with an example.

Please refer to my previous article to create ASP.NET Core Web API.

[React and .NET Core 6.0 Sample Project with Docker -Part 1](https://dev.to/jayavardhan5555/react-and-net-core-60-sample-project-with-docker-part-1-562i)

The sections of this post will be as follows:

Creating a ReactJs project
Install packages
Add Components
Test the React UI Application



So, Let's get started.

**Creating a ReactJs project:**

Open Command Prompt and navigate to the path where you want to create the React app.

`npx create-react-app movies-app`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f3iq8vm91tdogxm3sntq.png)

After creating the react project open the application using visual studio code.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q3retv7xpbcq0x9td5c4.png)

Go to Terminal => start the react app 

`npm start`

Once you start the project , the UI will be open in your default browser.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x5vvs1z6n9yvg2d5lbhu.png)

**Install packages:**

- npm install semantic-ui-react semantic-ui-css

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/49ybonuk9ybx5zx1vlff.png)

Open index.html page and past .css link in head section and .js after body section.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4plwsnefup1z30fuvc21.png)

- npm install axios

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9jr4tskjsk80wxjgca9w.png)

- npm install react-toastify


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/269p1af7vpv6qq5y50pr.png)

**Add Components**

Go to => src => Create "Components" folder 

- Components => NavBar.jsx

This will add the navigation bar to the application.

```javascript
import { Button, Menu } from "semantic-ui-react";
import "../index.css";

export default function NavBar(props) {
  return (
    <Menu inverted fixed="top">
      <Menu.Item header>
        <img
          src="/movieslogo.png"
          alt="logo"
          style={{ marginRight: "10px", marginLeft: "10px" }}
        />
        Movies
      </Menu.Item>
      <Menu.Item>
        <Button positive content="Add Movie" onClick={() => props.addForm()} />
      </Menu.Item>
    </Menu>
  );
}
```

- Components => MoviesTable.jsx

This component will display the table with movie details and actions to to delete and edit the movie.

```javascript
import { Fragment } from "react";
import { Table, Button } from "semantic-ui-react";
import "../index.css";

export default function MoviesTable(props) {
  return (
    <Fragment>
      <h1 style={{ marginLeft: "30px" }}>Movies List</h1>
      <Table
        celled
        style={{
          marginLeft: "30px",
          marginTop: "30px",
          width: "1100px",
          border: "1px solid black",
        }}
      >
        <Table.Header>
          <Table.Row>
            <Table.HeaderCell>Title</Table.HeaderCell>
            <Table.HeaderCell>Language</Table.HeaderCell>
            <Table.HeaderCell>Year</Table.HeaderCell>
            <Table.HeaderCell>OTT</Table.HeaderCell>
            <Table.HeaderCell>Actions</Table.HeaderCell>
          </Table.Row>
        </Table.Header>
        <Table.Body>
          {props.movies.map((movie) => (
            <Table.Row key={movie.id}>
              <Table.Cell>{movie.title}</Table.Cell>
              <Table.Cell>{movie.movieLanguage}</Table.Cell>
              <Table.Cell>{movie.releaseYear}</Table.Cell>
              <Table.Cell>{movie.ott}</Table.Cell>
              <Table.Cell>
                <Button positive onClick={() => props.editForm(movie)}>
                  Edit
                </Button>
                <Button negative onClick={() => props.deleteMovie(movie.id)}>
                  {" "}
                  Delete
                </Button>
              </Table.Cell>
            </Table.Row>
          ))}
        </Table.Body>
      </Table>
    </Fragment>
  );
}

```
- Components => AddMovie.jsx

This component will be used to add the movie details to the database and display in movie table.

```javascript
import { Button, Form, Segment } from "semantic-ui-react";
import React, { useState } from "react";
import { toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
export default function AddMovie(props) {
  
  const initialState = {
    title: "",
    movieLanguage: "",
    releaseYear: "",
    ott: "",
  };

  const [movie, setMovie] = useState(initialState);

  function handleSubmit(e) {
    e.preventDefault();
    if (!movie.title) {
      toast.error("Please fill all the details !", {
        position: toast.POSITION.TOP_RIGHT,
      });
      return;
    }
    props.handleSumbit(movie);
    setMovie(initialState);
  }

  function handleInputChange(event) {
    const { name, value } = event.target;
    setMovie({ ...movie, [name]: value });
  }

  return (
    <>
      <h1 style={{ marginLeft: "15px" }}>Add Movie</h1>
      <Segment clearing style={{ marginRight: "30px", marginTop: "30px", marginLeft: "10px" }} >
        <Form onSubmit={handleSubmit} autoComplete="off">
          <Form.Input placeholder="Title" value={movie.title} name="title" onChange={handleInputChange} />
          <Form.Input placeholder="Language" value={movie.movieLanguage} name="movieLanguage" onChange={handleInputChange}/>
          <Form.Input placeholder="Year" value={movie.releaseYear} name="releaseYear" onChange={handleInputChange} />
          <Form.Input placeholder="OTT" value={movie.ott} name="ott" onChange={handleInputChange}/>
          <Button floated="right" positive type="submit" content="Submit" />
          <Button floated="right" type="button" content="Cancel" onClick={() => props.closeForm()}
          />
        </Form>
      </Segment>
    </>
  );
}

```

- Components => EditMove.jsx

  This component will be used to edit the movie data and update.

```javascript
import { Button, Form, Segment } from "semantic-ui-react";
import React, { useState } from "react";

export default function EditMovie(props) {
  const [movie, setMovie] = useState(props.movie);

  function handleSubmit(e) {
    e.preventDefault();
    props.handleEditMovie(movie);
  }

  function handleInputChange(event) {
    const { name, value } = event.target;
    setMovie({ ...movie, [name]: value });
  }

  return (
    <>
      <h1 style={{ marginLeft: "15px" }}>Edit Movie</h1>
      <Segment
        clearing
        style={{ marginRight: "30px", marginTop: "30px", marginLeft: "10px" }}
      >
        <Form onSubmit={handleSubmit} autoComplete="off">
          <Form.Input
            placeholder="Title"
            value={movie.title}
            name="title"
            onChange={handleInputChange}
          />

          <Form.Input
            placeholder="Language"
            value={movie.movieLanguage}
            name="movieLanguage"
            onChange={handleInputChange}
          />
          <Form.Input
            placeholder="Year"
            value={movie.releaseYear}
            name="releaseYear"
            onChange={handleInputChange}
          />

          <Form.Input
            placeholder="OTT"
            value={movie.ott}
            name="ott"
            onChange={handleInputChange}
          />
          <Form.TextArea
            placeholder="Description"
            value={movie.description}
            name="description"
            onChange={handleInputChange}
          />
          <Button floated="right" positive type="submit" content="Submit" />
          <Button
            floated="right"
            type="button"
            content="Cancel"
            onClick={() => props.closeForm()}
          />
        </Form>
      </Segment>
    </>
  );
}

```
  

- Components => MoviesDashboard.jsx

  This will be used to display the all movie related components.

```javascript
import { Grid } from "semantic-ui-react";
import AddMovie from "./AddMovie";
import MoviesTable from "./MoviesTable";
import EditMovie from "./EditMovie";

export default function MoviesDashboard(props) {
  return (
    <Grid>
      <Grid.Column width="10">
        <MoviesTable movies={props.movies} editForm={props.editForm} deleteMovie={props.deleteMovie}/>
      </Grid.Column>
      <Grid.Column width="6">
        {props.showAddForm && (<AddMovie closeForm={props.closeForm} handleSumbit={props.handleSumbit} />)}
        {props.showEditForm && ( <EditMovie movie={props.movie} closeForm={props.closeForm} handleEditMovie={props.handleEditMovie} />  )}
      </Grid.Column>
    </Grid>
  );
}
```
  
Update the App.js with the below code

```javascript
import axios from "axios";
import "./App.css";
import { v4 as uuid } from "uuid";
import NavBar from "./components/NavBar";
import { useEffect, useState } from "react";
import MoviesDashboard from "./components/MoviesDashboard";
import { toast, ToastContainer } from "react-toastify";
function App() {
  const [movies, setMovies] = useState([]);
  const [movie, setMovie] = useState();
  const [showAddForm, setshowAddForm] = useState(false);
  const [showEditForm, setshowEditForm] = useState(false);

  useEffect(() => {
    axios.get("http://localhost:5159/api/movies").then((response) => {
      setMovies(response.data);
    });
  }, [movies]);

  function handleEditMovie(movie) {
    axios({
      method: "put",
      url: `http://localhost:5159/api/movies/${movie.id}`,
      data: {
        Id: movie.id,
        Title: movie.title,
        MovieLanguage: movie.movieLanguage,
        ReleaseYear: movie.releaseYear,
        OTT: movie.ott,
      },
      config: {
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
        },
      },
    })
      .then((response) => {
        console.log(response);
        toast.success("Movie updated successfully", {
          position: toast.POSITION.TOP_RIGHT,
        });
      })
      .catch((error) => {
        console.log("the error has occured: " + error);
      });

    setMovies([...movies, movie]);
  }

  function handleSumbit(movie) {
    const data = {
      Id: uuid(),
      Title: movie.title,
      MovieLanguage: movie.movieLanguage,
      ReleaseYear: movie.releaseYear,
      OTT: movie.ott,
    };
    axios({
      method: "post",
      url: "http://localhost:5159/api/movies",
      data: data,
      config: {
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
        },
      },
    })
      .then((response) => {
        console.log(response);
        toast.success("Movie added successfully", {
          position: toast.POSITION.TOP_RIGHT,
        });
      })
      .catch((error) => {
        console.log("the error has occured: " + error);
      });

    setMovies([...movies, data]);
  }

  function addForm() {
    setshowEditForm(false);
    setshowAddForm(true);
  }

  function closeForm() {
    setshowAddForm(false);
    setshowEditForm(false);
    setMovie("");
  }

  function editForm(movie) {
    setMovie("");
    setshowAddForm(false);
    setshowEditForm(true);
    setMovie(movie);
  }

  function deleteMovie(id) {
    setshowEditForm(false);
    setMovie("");
    axios.delete(`http://localhost:5159/api/movies/${id}`).then(() => {
      toast.success("Movie deleted successfully", {
        position: toast.POSITION.TOP_RIGHT,
      });
    });

    setMovies([...movies.filter((x) => x.id !== id)]);
  }

  return (
    <div>
      <NavBar addForm={addForm} />
      <h1>Movies Data</h1>
      <MoviesDashboard
        movies={movies}
        showAddForm={showAddForm}
        showEditForm={showEditForm}
        editForm={editForm}
        movie={movie}
        deleteMovie={deleteMovie}
        closeForm={closeForm}
        handleSumbit={handleSumbit}
        handleEditMovie={handleEditMovie}
      />
      <ToastContainer position="top-center" />
    </div>
  );
}

export default App;

```

Update the index.css with the below code for styling

```javascript
body {
  background-color: #eaeaea !important;
}
.ui.inverted.top.fixed.menu {
  background-image: linear-gradient(135deg,rgb(233, 10, 204) 0%, rgb(155, 50, 133) 69%,rgb(104, 50, 85) 89%) !important;
}
```

**Test the Movies UI **

Home Page:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1jk5ifdqb0j8rxge92g1.png)

Add Movie :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m513hgmuxz8zxbvlo6bi.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efijr4ngeqoh84vwl23j.png)

Edit Movie : 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/foj8cur27hb7ez3fizoo.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cnzo0m9ea0fgdft7kxly.png)



In the next section we will explain the way to containerize the .NET Core 6.0 Web API and React applications.

You can find the full project in this [GitHub repository](https://github.com/jayavardhan5555/movies-app).