This article covers how to make a fully responsive and sleek Movie App with React. React is a JavaScript framework provided by Facebook and is used to build fully-featured web applications.
We will be following the below steps for creating our application:
Step 1: Creating the project: We will start by creating a new react project using the create-react-app tool. You can use the following command for creating one with the desired name. Please ensure that Node and npm are installed on the system.
npx create-react-app movie-app
Project Structure: We will then delete all the files that are not necessary. The file structure after deleting the files is given below:
Step 2: Open the “src” folder and select the App.js file and add the following code to it.
App.js
import React, { useState } from "react" ; import axios from "axios" ; import Search from "./components/Search" ; import Results from "./components/Results" ; import Detail from "./components/Detail" ; import "./App.css" ; function App() { const [state, setState] = useState({ s: "sherlock" , results: [], selected: {}, }); const searchInput = (e) => { let s = e.target.value; setState((prevState) => { return { ...prevState, s: s }; }); }; const search = (e) => { if (e.key === "Enter" ) { axios(apiurl + "&s=" + state.s).then(({ data }) => { let results = data.Search; console.log(results); setState((prevState) => { return { ...prevState, results: results }; }); }); } }; const openDetail = (id) => { axios(apiurl + "&i=" + id).then(({ data }) => { let result = data; setState((prevState) => { return { ...prevState, selected: result }; }); }); }; const closeDetail = () => { setState((prevState) => { return { ...prevState, selected: {} }; }); }; return ( <div className= "App" > <header className= "App-header" > <h1>Movie Mania</h1> </header> <main> <Search searchInput={searchInput} search={search} /> <Results results={state.results} openDetail={openDetail} /> { typeof state.selected.Title != "undefined" ? ( <Detail selected={state.selected} closeDetail={closeDetail} /> ) : ( false )} </main> </div> ); } export default App; |
App.css
* { margin : 0 ; padding : 0 ; box-sizing: border-box; } body { font-family : "montserrat" , sans-serif ; background : linear-gradient(to right , #000428 , #004e92 ); } header { width : 100% ; padding-top : 2 rem; padding-bottom : 1 rem; } header h 1 { color : #ffffff ; font-size : 4 rem; font-weight : 700 ; text-align : center ; } main { width : 100% ; max-width : 90% ; margin : 0 auto ; } .results { display : flex; flex-wrap: wrap; justify- content : center ; align-items: center ; /* margin: 0 -15px; */ } .results .result { width : 20% ; min-width : 250px ; background : #000000 ; max-height : 500px ; /* padding: 15px; */ margin : 20px 25px ; display : flex; flex- direction : column; cursor : pointer ; } .results .not-found { display : flex; flex- direction : column; justify- content : center ; align-items: center ; text-align : center ; margin : 2 rem 0.5 rem; } .results .not-found h 2 { color : #ffffff ; } .results .result img { /* display: block; */ width : 100% ; padding : 10px 2px ; margin : 0 auto ; height : 350px ; width : 230px ; } .results .result h 3 { color : #fff ; font-size : 20px ; font-weight : 600 ; width : 100% ; text-align : center ; padding : 1 rem; background : #272829 ; flex: 1 100% ; transition: 0.4 s ease-out; } .result:hover { box-shadow: 0 0 8px 3px #eaf0f7 ; /* background: #dfd8d8; */ } .results .result h 3: hover { background : #fff ; color : #223343 ; box-shadow: 0 0 8px 3px #4484c4 ; } .detail { margin : 3 rem 5 rem; overflow-y: scroll ; } .detail .content .rating { margin-left : 2 rem; font-size : 1.5 rem; margin-bottom : 0 ; margin-top : 1 rem; padding-bottom : 0 ; } .detail .content { display : block ; width : 100% ; height : 100% ; position : fixed ; top : 0 ; left : 0 ; max-width : 15000px ; /* max-height: 600px; */ padding : 25px ; background : #000000 ; color : #fff ; overflow-y: scroll ; } .detail .content h 2 { font-size : 3 rem; padding : 2 rem; padding-top : 0 ; padding-bottom : 0.5 rem; font-weight : 600 ; } .detail .content span { font-size : 1.4 rem; margin-left : 2 rem; margin-bottom : 3 rem; font-weight : 300 ; color : #ffffff ; } .detail .content .rating { margin-bottom : 30px ; } .detail .content .about { display : flex; flex-wrap: wrap; margin : 0 -15px 30px ; } .detail .content .about img { flex: 1 1 50% ; max-width : 300px ; opacity: none ; padding : 0 15px ; margin-left : 2 rem; margin-top : 1 rem; } .detail .content .about p { flex: 1 50% ; padding : 15px 25px ; margin-top : 3 rem; font-size : 1.5 rem; } .detail .content .close { /* display: inline-block; */ padding : 15px 30px ; font-size : 18px ; /* margin-top: 3rem; margin-right: 2rem; margin-bottom: 1rem; */ font-weight : 700 ; background : #223343 ; color : #fff ; /* border-radius: 8px; */ border : none ; outline : none ; appearance: none ; cursor : pointer ; transition: 0.4 s ease-out; width : 100% ; display : flex; margin : auto ; margin-top : 5 rem; justify- content : center ; align-items: center ; border-radius: 5px ; } .detail .content button:hover { background : #4484c4 ; } .detail .content .about .close:hover { background : #223343 ; } @media screen and ( max-width : 1015px ) { .results { justify- content : center ; align-items: center ; } .detail .content .close { width : 100% ; display : flex; margin : auto ; justify- content : center ; align-items: center ; border-radius: 5px ; } } @media screen and ( max-width : 683px ) { .results { justify- content : center ; align-items: center ; } .results .result { margin : 10px ; justify- content : center ; align-items: center ; } } @media screen and ( max-width : 643px ) { .results .result { margin : 15px ; } } @media screen and ( max-width : 638px ) { .results .result { margin : 8px ; } } @media screen and ( max-width : 410px ) { header h 1 { font-size : 2.9 rem; } .results { display : flex; flex- direction : column; justify- content : center ; align-items: center ; } .detail { overflow-y: scroll ; } .detail .content .close { width : 100% ; display : flex; margin : auto ; justify- content : center ; align-items: center ; border-radius: 5px ; } .detail .content span { margin-left : 0.5 rem; font-style : italic ; font-weight : bold ; } .detail .content h 2 { padding-left : 0.5 rem; font-size : 2.1 rem; margin-bottom : 0.5 rem; font-weight : 100 ; } .detail .content .rating { margin-left : 0.5 rem; font-weight : bold ; } .detail .content .about img { margin-left : 0.5 rem; } } |
Step 3: Make a new folder named Components in your src folder. In the src folder, make files – Detail.js, Result.js, Results.js, Search.js, and Search.css
Step 4: Now add the following codes in the respective files.
Detail.js
import React from "react" ; function Detail({ selected, closeDetail }) { return ( <section className= "detail" > <div className= "content" > <h2>{selected.Title}</h2> <span>{selected.Year}</span> <p className= "rating" >Rating: {selected.imdbRating}</p> <div className= "about" > <img src={selected.Poster} alt= "" /> <p>{selected.Plot}</p> </div> <button className= "close" onClick={closeDetail}> Close </button> </div> </section> ); } export default Detail; |
Result.js
import React from "react" ; function Result({ result, openDetail }) { return ( <div className= "result" onClick= {() => openDetail(result.imdbID)}> <img src={result.Poster} /> <h3>{result.Title}</h3> </div> ); } export default Result; |
Results.js
import React from "react" ; import Result from "./Result" ; function Results({ results, openDetail }) { return ( <section className= "results" > { typeof results != "undefined" ? ( results.map((result) => ( <Result key={result.imdbID} result ={result} openDetail={openDetail} /> )) ) : ( <div className= "not-found" > <h2>Sorry.. Movie not found in the database.</h2> <h2> Try checking the name you input or search for another movie. </h2> </div> )} </section> ); } export default Results; |
Search.js
import React from "react" ; import "./Search.css" ; function Search({ searchInput, search }) { return ( <div className= "search-bar" > <input type= "text" placeholder= "Search for a Movie..." className= "search" onChange={searchInput} onKeyPress={search} /> </div> ); } export default Search; |
Search.css
.search-bar { display : flex; justify- content : center ; align-items: center ; margin : 1 rem 0 ; } .search { width : 60% ; display : block ; padding : 15px ; border : none ; outline : none ; background : none ; background-color : #fff ; border-radius: 8px ; color : dimgrey; font-size : 20px ; font-weight : 300 ; transition: 0.4 s ease-out; } .search:focus { box-shadow: 0 0 8px 3px #4484c4 ; } @media screen and ( max-width : 685px ) { .search { width : 75% ; } } @media screen and ( max-width : 410px ) { .search { width : 85% ; } } |
Step 5: Running and Building the application: We can run this application by using the following command. This will start React’s development server that can be used for debugging our application.
npm run start
Output: You will see the following output on your browser screen.