Today we’ll learn how to build a simple web app that lets a user find and display information about their favorite movies using the RapidAPI IMDb Alternative. IMDb has a publicly accessible API, however, it is undocumented and difficult to use. The RapidAPI alternative – which is also free – provides an easier way to interface with the database.
In this tutorial, we’ll build a complete front end app using React. We’ll focus on building the app itself, so if you haven’t already, check out this article for information about how to get started with the RapidAPI IMDb Alternative. This tutorial assumes you have npm > 5.2.0 and Node > 8.0.0 installed. If you’re not sure how to install those, check out this article.
Getting Started with React
We’ll use a library called Create React App to get ourselves set up with React. Create React App is a toolchain that bundles together the tools (Webpack, Babel, Jest, ESLint, etc.) that make developing with React easy (and fun!) It is possible to build and configure your own toolchain, but as every good developer knows, “there’s no need to reinvent the wheel!” Create React App will give us everything we need to build an awesome app right out of the box.
Navigate to the directory where you keep your coding projects. Here’s everything you need to do in order to get your app up and running:
npx create-react-app my-movie-app cd my-movie-app yarn start
*Note: npx here is not a typo – it’s a package runner that ships with npm 5.2.0 and above. Learn more about it here. Never used yarn? It’s an npm alternative that ships with create-react-app. Learn more here. If you prefer, you can use npm instead of yarn.
That’s it! Easy right? You should now be able to navigate to http://localhost:3000 and see a welcome page that looks like this
Let’s open up the project with our favorite text editor (I recently started using VSCode, but I’m also a fan of Atom.)
code .
There are two folders here: /public and /src. We won’t worry about the /public folder for now – all our work will take place in src/App.js. Open up this file and take a look at what’s given to you
This is the boilerplate that renders at localhost:3000. Delete everything between the <header>s, save the file, and take another look at the page in the browser. It should have automatically updated to a blank page. Awesome! Create React App handles hot module reloading for us so all our changes are automatically picked up.
Setting Up the API
Go to https://rapidapi.com/developer/dashboard. If you haven’t gone through this tutorial yet, you’ll need to do that first. Click “My Apps” and then click the little shield with a checkmark under “Security.”
On the next page, copy your API key.
Back in your project folder, run the following:
npm install --save unirest
This will install the SDK that fetches the info for us from IMDb. Once it’s installed, import it into your App.jsx file
import unirest from 'unirest';
Now let’s write a function called sendRequest that uses unirest to get our movie information.
sendRequest = (title) => { const req = unirest("GET", "https://movie-database-imdb-alternative.p.rapidapi.com/"); req.query({ "page": "1", "r": "json", "s": title }); req.headers({ "x-rapidapi-host": "movie-database-imdb-alternative.p.rapidapi.com", "x-rapidapi-key": "YOUR_API_KEY" }); req.end(function (res) { if (res.error) throw new Error(res.error); console.log(res.body); }); }
This unirest code is provided by RapidAPI. Paste your API key where it says “YOUR_API_KEY.” This function will take in the title of our movie and send a request to the IMDb search endpoint to get back the information we want. Right now we are just outputting the information with console.log. Paste this function inside your App function.
Building the App
Now that we’re able to get data from the API, we need to display it in our app. We’ll build a very simple search input that allows a user to type in the name of a movie they like. We’ll query the API for the movie data, and display the response in our UI.
React allows us to build specific components for each part of our UI. We’ll build a <Search>
component that lets a user input a movie title, and a <Movie>
component to display the movie. Then we’ll import both of these components to our main App file and render them.
The first thing we’ll do is make a small change to our main App component. The create-react-app boilerplate uses a stateless functional component for the main app. We are going to use the Class
keyword, which allows us to maintain state in our app. (You could also use hooks, but that’s a bit more complicated to explain, so we’ll save it for another post.)
In your App.js file, delete the word function
and replace it with class
. Now, after App
, add extends React.Component
, and delete the parentheses. Now rename the file from App.js to App.jsx. Your App class should now look like this:
class App extends React.Component {
We also need to add a Render function to our app. This is a function that tells the app to render some JSX (fancy HTML.) We already have the JSX inside our return statement, so we’ll just wrap that:
render() { return ( <div className="App"> <header className=”App-header”> </header> </div> ); }
Our complete App.jsx file should now look like this
import React from 'react'; import './App.css'; import unirest from 'unirest'; class App extends React.Component { sendRequest = (title) => { const req = unirest("GET", "https://movie-database-imdb-alternative.p.rapidapi.com/"); req.query({ "page": "1", "r": "json", "s": title }); req.headers({ "x-rapidapi-host": "movie-database-imdb-alternative.p.rapidapi.com", "x-rapidapi-key": "YOUR_API_KEY" }); req.end((res) => { if (res.error) throw new Error(res.error); console.log(res.body); }); } render() { return ( <div className="App"> <header className="App-header"> </header> </div> ); } } export default App;
Creating a Search Component
Create a new file called Search.jsx
and paste in this code:
import React from 'react'; class Search extends React.Component { state= { title: '' } handleSubmit = () => { const {title} = this.state; this.props.handleSendRequest(title) this.setState({title: ''}) } handleInputTitle = (event) => { event.preventDefault(); const title = event.target.value; this.setState({title}); } render() { const {title} = this.state; return ( <div className="search"> <input className="search-box" type="text" onChange={this.handleInputTitle} value={title}/> <input className="button" type="submit" onClick={this.handleSubmit} value="Search"/> </div> ) } } export default Search;
This is a simple React class that renders a text input and a button. It has some state that stores the title of the movie the user inputs – this title gets updated via our handleInputTitle function every time the user types into the input box. Once the user has finished inputting the title, clicking the “Search” button will call our handleSubmit function, which sends the title to RapidAPI to look up the movie.
You should notice that handleSubmitFunction actually calls another function: this.props.handleSendRequest. We’ll talk more about this in a minute.
Create another file in the same file as your App file called Search.css
and paste in the following:
.search { display: flex; justify-content: space-between; width: 25% } .search-box { width: 60%; height: 46px; font-size: 16px; } .button { background-color: rgb(76, 175, 137); border: none; color: white; padding: 15px 32px; text-align: center; text-decoration: none; font-size: 16px; cursor: pointer; }
And add this line to your Search.jsx file:
import "./Search.css";
We already added all the classNames into the Search file. Now your app will start to look pretty and not like something out of 1995. Huzzah!
Create a Movie Component
Create a file in the same folder called Movie.jsx
and paste this code
import React from 'react'; class Movie extends React.Component { render() { const {Title, Poster, Year} = this.props; return ( <div className="movie"> <div className="title-year"> <h1 className="title">{Title}</h1> <h2 className="year">{Year}</h2> </div> <div className="poster"> <img src={Poster} alt="my movie poster"/> </div> </div> ) } } export default Movie;
Notice that we are pulling things out of this.props
again – our title, poster and year. Don’t worry about that yet – I promise we’re getting there! For now, create another CSS file (Movie.css
) and add the following:
.movie { width: 75%; color: white; } .title-year { display: flex; justify-content: space-between; align-items: center; } .title, .year { font-weight: bold; } .poster { border-radius: 5%; }
And add this line into your Movie.jsx file:
import "./Movie.css";
Sweet! We’ve got all our components together. We almost have a fully functioning app!
Putting It All Together
So we have a component to search for a movie, we have a function that’s pulling data from our API, and we have a component to display the title, year and poster. But in order to actually get our information into those components, we need to use two special React features: State and Props.
We already used state in our Search component to store the title of the movie the user is searching for. We will use state in our App component to store the information we get back from the API. Let’s add the following to our App component
class App extends React.Component { state = { movies: [] }
This is where we’ll store our data. Notice that we’re preparing to store multiple movies – this is because the IMDb Alternative returns all the movies it can find for a given search term. So if our user types in “Avengers” she will get back a list of all the Avengers movies. We want to render the posters for all of them.
Now let’s update our sendRequest
function:
req.end((res) => { if (res.error) throw new Error(res.error); const movies = res.body.Search; this.setState({movies}); });
Here’s where the magic happens! We’re pulling our movies out of the response data, and storing them in our app state.
Now we just have to pass this to our Movie component as props. But first, we need to import our Movie component into our App. Add this to the top of your App component:
import Movie from "./Movie.jsx";
Inside the <header> tags in our Render function, add this:
{ this.state.movies.map((movie) => { return <Movie {...movie}/> }) }
Now our App component will render the Movie component, and pass down the data it received from the API.
But wait! We still haven’t hooked up our Search component! So we still can’t get any data. Right now, our Search button doesn’t actually do anything.
We still need to render our Search component, and pass the function to it that will handle sending our request to the API. Let’s do that now.
import Search from "./Search.jsx";
And between the <header> tags inside the Render function, add this:
<Search handleSendRequest={this.sendRequest}/>
Awesome! Now our app does everything. To summarize, here’s what we did:
- Built a component that lets a user search for a movie by title
- Stored the movie title in that component’s state
- Got an API key for the IMDb API from RapidAPI
- Copied some code from RapidAPI that uses the API key to send a request to IMDb
- Passed the function to the search component so we could call it when we click the button
- Store the response in the App state
- Built a component that displays the response data we got from the API
- Passed the response data to this child component
- Showed the data to the user
Pretty easy, right?
Obviously, there are a lot of other things you would need to consider before deploying this application. What if the user types in a movie that isn’t in the database? What if the database returns duplicates? What if your API key expires, or you go over the monthly limit? What if the user types in some code that runs a virus?
These are all excellent questions that are unfortunately out of the scope of this tutorial. I encourage you to explore these questions on your own and keep expanding this basic app. And of course, keep exploring RapidAPI to discover more APIs that you can leverage for your personal projects and production apps.
iyin says
TypeError: Cannot read property ‘Search’ of undefined
(anonymous function)
23 | });
24 | req.end((res) => {
25 | if (res.error) throw new Error(res.error);
> 26 | const movies = res.body.Search;
| ^ 27 | this.setState({movies});
28 | // console.log(res.body.Search);
29 | });
Elavarasan N says
hey iyin , where do u find the source code..? plss send the github code
shubham says
What do u mean by inside the header tags and between the header tags????
this is between
But what is inside???
Jonny says
is it possible for the source code on github ?
RapidAPI Staff says
Hi Jonny,
Please reach out to support@rapidapi.com for additional support
Josh says
Error: got 403 response
(anonymous function)
C:/Users/Chisom/Desktop/my-movie-app/src/App.js:28
25 |
26 |
27 | req.end((res) => {
> 28 | if (res.error) throw new Error(res.error);
| ^ 29 | const movies = res.body.Search;
30 | this.setState({movies});
31 | console.log(res.body.Search);
khush says
(anonymous function)
C:/Users/Chisom/Desktop/my-movie-app/src/App.js:28
25 |
26 |
27 | req.end((res) => {
> 28 | if (res.error) throw new Error(res.error);
| ^ 29 | const movies = res.body.Search;
30 | this.setState({movies});
31 | console.log(res.body.Search);
….reply of this error ..and give solution