---
layout: post
title: Path to frontend master I
date: 2019-10-11
tags:
    - javascript
    - react
lang: en
## Make sure to change these
published: true
sitemap: false
---

I decided to start a series of front end projects that I found at
DEV.to "[9 Projects you can do to become a frontend Master in
2020](https://dev.to/simonholdorf/9-projects-you-can-do-to-become-a-frontend-master-in-2020-n2h)".
This post is about my own spin-off from the first project listed in that
post by Simon Holdorf, a movie search app
using React with hooks only, avoiding Class based components.

The fact that the challenge involves using the new hooks feature in
React interests me particularly, because I recently revisited React
after I learnt it one year and a half ago, then I left front end
completely all this time. The base for my spin off comes from Samuel
Omole's [tutorial](https://www.freecodecamp.org/news/how-to-build-a-movie-search-app-using-react-hooks-24eb72ddfaf7/)
at freecodecamp.org

The `Header` and `Movie` components are almost identical to the ones
Samuel wrote, but I took a few liberties in the `Search` and `App`
components. Also I prefer `.jsx` extensions for components and `.js` for
plain old javascript code. However I encourage you to read his tutorial
because he goes deeper in the logic behind the app and explains how the
hooks work, it is not my goal to repeat him.

What I do different?
- OMDB API key is not exposed in the React app
- A [OpenFaaS](https://www.openfaas.com/) server-less function acts as proxy to OMDB
- keywords for narrowing the search and limiting number of results:
    - title:_"movie title"_
    - type:_movie, series, episode_
    - limit:_12_

[create-react-app](https://create-react-app.dev/) is the tool I am more
used to bootstrap React projects, honestly I haven't tried many others
besides Gatsby. I became a patron at
[CodeSandbox](https://codesandbox.io) so why not use it for this
project?  The `codesandbox` cli made a breeze to export the project I
had already bootstrapped from my laptop to the web editor. You can also
bootstrap your project directly in CodeSandbox and then export to a
Github repository and or publish it to Netlify. Go and check them out!

```bash
npm install -g codesandbox
codesandbox ./
```

Move `App.js` and `App.css` to `components/App.js`.

Add `components/Header.jsx`.

<iframe
src="https://codesandbox.io/embed/avocado-mdshc?codemirror=1&fontsize=14&module=%2Fsrc%2Fcomponents%2FHeader.jsx&view=editor"
title="avocado" allow="geolocation; microphone; camera; midi; vr;
accelerometer; gyroscope; payment; ambient-light-sensor;
encrypted-media; usb" style="width:100%; height:500px; border:0;
border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms
allow-popups allow-scripts allow-same-origin"></iframe>

Also add a `components/Movie.jsx` file:

<iframe
src="https://codesandbox.io/embed/avocado-mdshc?codemirror=1&fontsize=14&module=%2Fsrc%2Fcomponents%2FMovie.jsx&view=editor"
title="avocado" allow="geolocation; microphone; camera; midi; vr;
accelerometer; gyroscope; payment; ambient-light-sensor;
encrypted-media; usb" style="width:100%; height:500px; border:0;
border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms
allow-popups allow-scripts allow-same-origin"></iframe>

The next component `components/Search.jsx` will introduce **hooks**, the
new React feature that allow to handle state in functional components. I
really do not like the idea of classes in JavaScript and since I am not
a long time React developer I very much welcome hooks.

<iframe
src="https://codesandbox.io/embed/avocado-mdshc?codemirror=1&fontsize=14&module=%2Fsrc%2Fcomponents%2FSearch.jsx&view=editor"
title="avocado" allow="geolocation; microphone; camera; midi; vr;
accelerometer; gyroscope; payment; ambient-light-sensor;
encrypted-media; usb" style="width:100%; height:500px; border:0;
border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms
allow-popups allow-scripts allow-same-origin"></iframe>

In the Search component the `useState` hook takes the initial state as
parameter and returns an array with the current state (similiar to
`this.state` but does not merge old and new states togheter) and a
function to update the state `setSearchValue` in this case, which is the
same as `this.setState`.

`useEffect` is a hook which allows to perform _side effects_ in your
components, like fetching data from OMDB in this app. Other hook is
`useReducer` which works similar to redux reducers, it accepts state and
action and returns the current state and a dispatch method.

<iframe
src="https://codesandbox.io/embed/avocado-mdshc?codemirror=1&fontsize=14&module=%2Fsrc%2Fcomponents%2FApp.jsx&view=editor"
title="avocado" allow="geolocation; microphone; camera; midi; vr;
accelerometer; gyroscope; payment; ambient-light-sensor;
encrypted-media; usb" style="width:100%; height:500px; border:0;
border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms
allow-popups allow-scripts allow-same-origin"></iframe>

There are a couple of unbreakable rules for using hooks in React, **only
call hooks at the top level of function components**. Do not call hooks
inside loops, conditions or nested functions. **Only call hooks from
React function components**. Do not call hooks from regular JavaScript
functions.

You can read more about [Hooks](https://reactjs.org/docs/hooks-intro.html) in the React docs.

In conclusion , I will be using hooks over class based components in my
current and next React projects, a good thing is that class and function
components with hooks mix well, so no heavy refactoring of
class components and slow adoption of hooks is a good approach for
existing projects.

You can try and explore the code for the working movie app. Be ware!
Since this is a demo the server-less function behind is not setup to
scale and a heavy load of requests may take it down temporarily.

<iframe
src="https://codesandbox.io/embed/avocado-mdshc?codemirror=1&fontsize=14&module=%2Fsrc%2Fcomponents%2FApp.jsx"
title="avocado" allow="geolocation; microphone; camera; midi; vr;
accelerometer; gyroscope; payment; ambient-light-sensor;
encrypted-media; usb" style="width:100%; height:500px; border:0;
border-radius: 4px; overflow:hidden;" sandbox="allow-modals
allow-forms allow-popups allow-scripts allow-same-origin"></iframe>