This article will explain how to create React Js application and consume ASP.NET Core Web API requests to fetch the movie's data.
We will go through step by step with an example.
Please refer to my previous article on how to create ASP.NET Core Web APIs to fetch the data.
We need the following tools installed on our computer,
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 the Command Prompt and navigate to the path where you want to create the React application.
Command to create a React App: npx create-react-app movies-app
Open the application using Visual Studio Code.
Go to Terminal => start the react app using "npm start"
Once you start the project, the UI will be open in your default browser.
Install packages
Go to VsCode Terminal and execute the below NPM packages one by one.
Add Components
Go to Movies App folder in VS Code => src => Create "Components" folder
Step 1
Create a .jsx file in the components folder and name it NavBar.jsx
We will use this file to add the Navigation to our Movies Application.
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>
);
}
Now create one more file for the movies table and name it as MoviesTable.jsx
This component displays the table with movie details and actions to delete and edit the movie.
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 them in the movie table.
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 => EditMovie.jsx
This component will be used to edit the movie data and update it.
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 all movie related components.
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.
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.
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;
}
Now go to the browser where we started the application.
Home Page
Add Movie
Edit Movie
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.
Thanks for reading!
Please leave a comment if you find this helpful. Any feedback or suggestions are welcome.