creando una base de datos de películas con la API de OMDB y REACT
Tags: react, javascript, beginners, tutorial
Published: 2022-06-09 20:35:00

En el siguiente post aprenderemos a crear una aplicación muy básica y sencilla con React, donde integraremos la API de OMDB (https://www.omdbapi.com/), para obtener una key es sencillo, debes ingresar a la página, ir a la sección de API key, colocar el tipo de cuenta gratis, y colocar tu correo, unos momentos después recibirás la key en tu correo.

[Puedes contactarme por telegram si necesitas contratar a un desarrollador Full Stack.](https://t.me/rtagliajs)

También puedes contactarme por **discord Appu#9136**

## Creación del proyecto
- abrir la terminal
- ubicarnos en la carpeta donde vamos a querer crear nuestro proyecto
- npx create-react-app react-omdb (o como desees nombrarlo)
- cd react-omdb (o el nombre que le hayas colocado)
- code .

El CSS que se usó para este ejemplo es muy sencillo, puedes copiarlo o descargarlo de este link (https://github.com/rtagliaviaz/react-omdb-tut/blob/main/src/App.css) o hacer tu propia interfaz si así lo deseas.

## Estructura del proyecto:

react-omdb/
├── node_modules/
├── public/
├── src/
│   ├── components/
│   ├── App.css
│   ├── App.js
│   └── index.css
│   └── index.js
└── package.json

## Dependencias
- axios

Para este ejemplo solo instalaremos axios como dependencia adicional, lo haremos abriendo la consola ubicados en nuestro proyecto, seguido de `npm i axios`.

Finalmente para poder empezar, volveremos abrir la consola y ejecutaremos el siguiente comando `npm start` para poder ver los cambios que realizaremos a lo largo de este post.

## Tabla de Contenido

1. Creación del componente Main.js
2. Integración de la API
3. Obtener información de la película
4. Creación y Configuración del modal para mostrar los detalles
5. Paginación
6. Conclusión

---

### Empecemos!

1. ## Creación del componente Main.js

Para empezar lo primero que haremos será eliminar los archivos que no usaremos, dejando nuestro proyecto como se muestra mas arriba en la estructura del proyecto.

Abriremos nuestro archivo `App.js` ubicado dentro de src, vamos a eliminar el import del logo, y modificaremos nuestro archivo dejándolo de la siguiente manera por los momentos.

```js
import './App.css';

function App() {
  return (
    <div className="App">
      REACT OMDB
    </div>
  );
}

export default App;
```

Posterior a esto iremos a nuestra carpeta components dentro de la carpeta src (la crearemos en caso de no haberla creado aun), dentro de components crearemos un archivo llamado `Main.js` .

Abriremos nuestro `Main.js`, empezaremos importando los hooks `useState` y `useEffect` ya que los usaremos mas adelante, y también importaremos axios.

Crearemos una constante con el nombre de api donde colocaremos la ruta de la api, en este caso 'https://www.omdbapi.com/?' y también una constante para apiKey a la que le asignaremos nuestra key.

De momento solo retornaremos un div con el nombre de nuestro componente.

```js
import React, {useState, useEffect} from 'react'
import axios from 'axios'

//api

const api = 'https://www.omdbapi.com/?'

//api key
const apiKey = 'apikey=18eaeb4f'

const Main = () => {
  
  return(
    <div>
      Main
    </div>
  )
}

export default Main
```

Volveremos a nuestro `App.js` y importaremos nuestro componente `Main.js` como se muestra en el código de abajo, veremos que ya nos muestra el componente `Main.js`.


```js
import React from 'react';
import './App.css'
//components
import Main from './components/Main'

function App() {
  return (
    <div className="App">
      REACT OMDB
      <Main />
    </div>
  );
}

export default App;
```

![Hello World](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l4db0f2xa80dc83u4l8v.png)

2. ## Integración de la API

Ahora volveremos a nuestro componente `Main.js` y haremos un formulario para poder realizar una búsqueda con el nombre de la película, y hacer uso del hook `useState`, al hacer clic al botón de buscar se ejecutará la función que realizará la petición GET a la api, y de momento obtendremos la respuesta por consola.

```js
import React, { useState, useEffect } from "react";
import axios from "axios";

//api

const api = "https://www.omdbapi.com/?";

//api key
const apiKey = "apikey=18eaeb4f";

const Main = () => {
  const [name, setName] = useState("");

  //get response from API
  const getInfo = () => {
    axios
      .get(api + apiKey + `&s=${name}` + "&type=movie" + "&page=1")
      .then((res) => {
        if (res) {
          console.log(res.data);
        }
      });
  };

  //submit the title entered
  const handleSubmit = (e) => {
    e.preventDefault();
    getInfo();
  };

  return (
    <div>
      <form>
        <div className='searchBar'>
          <label htmlFor='name'></label>
          <input
            type='text'
            name='name'
            placeholder='movie name'
            onChange={(e) => setName(e.target.value)}
          />
          <button type='submit' onClick={(e) => handleSubmit(e)}>
            Search
          </button>
        </div>
      </form>
    </div>
  );
};

export default Main;
```

![api response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/el80xhfzbhasxbefqgbx.png)

Estamos recibiendo un objeto, con el número total de resultados (que usaremos mas adelante para crear la funcionalidad de paginación), y un arreglo con los 10 primeros títulos que encontró, con detalles como el poster, la fecha de estreno, el imdbID (que también usaremos mas adelante), y muchos más.

Usaremos nuevamente nuestro `useState`, en este caso con un arreglo de películas con el estado inicial vacío, y cambiará cuando obtengamos los resultados. Y ahora en el return devolveremos la lista de resultados si el arreglo tiene elementos, en caso contrario devolveremos `null`.

Haremos que nos devuelva por cada título, un poster, el título, y un botón details, que de momento no hace nada, y colocaremos como key el imdbId de cada título.

```js
import React, { useState, useEffect } from "react";
import axios from "axios";

//api

const api = "https://www.omdbapi.com/?";

//api key
const apiKey = "apikey=18eaeb4f";

const Main = () => {
  const [name, setName] = useState("");
  const [movies, setMovies] = useState([])

  //get response from API
  const getInfo = () => {
    axios
      .get(api + apiKey + `&s=${name}` + "&type=movie" + "&page=1")
      .then((res) => {
        if (res) {
          setMovies(res.data.Search)
        }
      });
  };

  //submit the title entered
  const handleSubmit = (e) => {
    e.preventDefault();
    getInfo();
  };

  return (
    <div>
      <form>
        <div className='searchBar'>
          <label htmlFor='name'></label>
          <input
            type='text'
            name='name'
            placeholder='movie name'
            onChange={(e) => setName(e.target.value)}
          />
          <button type='submit' onClick={(e) => handleSubmit(e)}>
            Search
          </button>
        </div>
      </form>

      {movies ? 
      <div className="movies">
        {movies.map(movie => (
          <div key={movie.imdbID} className="movie">
            <img src={movie.Poster} alt=""/>
            <div className="movie-title">
              <p>{movie.Title}</p>
            </div>
            <button className="movie-detailsBtn" >Details</button>

          </div>))}
      </div> 
      : null}
    </div>
  );
};

export default Main;
```

![movies displayed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/inf8ukhb0dmsd7pfu8v8.png)

3. ## Obtener información de la película

Ahora para el botón de detalles crearemos una función llamada `getDetails`, la cual se la pasará como argumento el id (imdbID) del título y se hará otra petición GET a la api con el id para que nos devuelva específicamente los datos de esa película, de momento los mostraremos por consola.

```js
import React, { useState, useEffect } from "react";
import axios from "axios";

//api
const api = "https://www.omdbapi.com/?";

//api key
const apiKey = "apikey=18eaeb4f";

const Main = () => {
  const [name, setName] = useState("");
  const [movies, setMovies] = useState([])

  //get response from API
  const getInfo = () => {
    axios
      .get(api + apiKey + `&s=${name}` + "&type=movie" + "&page=1")
      .then((res) => {
        if (res) {
          setMovies(res.data.Search)
        }
      });
  };



  //submit the title entered
  const handleSubmit = (e) => {
    e.preventDefault();
    getInfo();
  };

  return (
    <div>
      <form>
        <div className='searchBar'>
          <label htmlFor='name'></label>
          <input
            type='text'
            name='name'
            placeholder='movie name'
            onChange={(e) => setName(e.target.value)}
          />
          <button type='submit' onClick={(e) => handleSubmit(e)}>
            Search
          </button>
        </div>
      </form>

      {movies ? 
      <div className="movies">
        {movies.map(movie => (
          <div key={movie.imdbID} className="movie">
            <img src={movie.Poster} alt=""/>
            <div className="movie-title">
              <p>{movie.Title}</p>
            </div>
            <button className="movie-detailsBtn" >Details</button>

          </div>))}
      </div> 
      : null}
    </div>
  );
};

export default Main;
```

![movie details from api](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ygxce3ef5mnorekrsp7s.png)

Vamos a añadir un estado de `movieDetails` que este inicializado como un objeto vacío, ahora en lugar de mostrar los detalles por consola vamos a actualizar el estado de `movieDetails` con esos datos.

```js
import React, { useState, useEffect } from "react";
import axios from "axios";

//api

const api = "https://www.omdbapi.com/?";

//api key
const apiKey = "apikey=18eaeb4f";

const Main = () => {
  const [name, setName] = useState("");
  const [movies, setMovies] = useState([])
  const [movieDetails, setMovieDetails] = useState({})

  //get response from API
  const getInfo = () => {
    axios
      .get(api + apiKey + `&s=${name}` + "&type=movie" + "&page=1")
      .then((res) => {
        if (res) {
          setMovies(res.data.Search)
        }
      });
  };

  //get details
  const getDetails = (e, id) => {
    e.preventDefault()

    axios.get(api + apiKey + `&i=${id}`).then((res) => {
      if (res) {
        setMovieDetails(res.data)
      }
    })
  }

  //submit the title entered
  const handleSubmit = (e) => {
    e.preventDefault();
    getInfo();
  };

  return (
    <div>
      <form>
        <div className='searchBar'>
          <label htmlFor='name'></label>
          <input
            type='text'
            name='name'
            placeholder='movie name'
            onChange={(e) => setName(e.target.value)}
          />
          <button type='submit' onClick={(e) => handleSubmit(e)}>
            Search
          </button>
        </div>
      </form>

      {movies ? 
      <div className="movies">
        {movies.map(movie => (
          <div key={movie.imdbID} className="movie">
            <img src={movie.Poster} alt=""/>
            <div className="movie-title">
              <p>{movie.Title}</p>
            </div>
            <button className="movie-detailsBtn" 
            onClick={e => getDetails(e, movie.imdbID)}
            >Details</button>

          </div>))}
      </div> 
      : null}
    </div>
  );
};

export default Main;
```

4. ## Creación y Configuración del modal para mostrar los detalles

Para mostrar estos datos usaremos un modal que se muestre cada vez que hagamos clic en el botón "details", para esto iremos a nuestra carpeta components y crearemos un archivo llamado `MovieModal.js`, el cual de momento nos va a retornar esta estructura, (recuerda que las clases corresponden al css que cree).

```js
const MovieModal = () => {
  return(
    <div className="modal display-block">
      <section className="modal-main">
        <div className="modal-body">
          
        </div>
        <button className="modal-closebtn" >Close</button>
      </section>
    </div>
  )
}

export default MovieModal
```

Ahora para poder abrir este modal debemos volver a nuestro archivo `Main.js`:

1- Empezamos importando nuestro nuevo componente.

2- Declaramos un estado para el id seleccionado `$const [selectedId, setSelectedId] = useState(null)` .

3- Vamos a crear un estado para mostrar nuestro modal con `$const [show, setShow] = useState(false)` que será un booolean y estará inicializado en false.

4- Configuraremos la funcionalidad del modal con 3 funciones.

5- En nuestra función getDetails actualizaremos selectId con el id que se paso como argumento a la función, luego al recibir la respuesta ejecutaremos `showModal()` para mostrarlo.

6- Por ultimo en return debajo del botón colocaremos una condicional, si `MovieDetails` no esta vacío, si el selectedId es estrictamente igual al imdbdID de la película y si show esta en true, entonces nos va a retornar el componente de nuestro modal, de lo contrario no lo mostrará.

```js
import React, { useState, useEffect } from "react";
import axios from "axios";

//components
import MovieModal from "./MovieModal";

//api
const api = "https://www.omdbapi.com/?";

//api key
const apiKey = "apikey=18eaeb4f";

const Main = () => {
  const [name, setName] = useState("");
  const [movies, setMovies] = useState([])
  const [selectedId, setSelectedId] = useState(null)
  const [movieDetails, setMovieDetails] = useState({})

  //modal
  const [show, setShow] = useState(false)


  //modal config

  const showModal = () => {
    setShow(true)
  }

  const hideModal = () => {
    
    setShow(false)
    setMovieDetails()
  }

  const handleClose = () => {
    hideModal()
  }

  //get response from API
  const getInfo = () => {
    axios
      .get(api + apiKey + `&s=${name}` + "&type=movie" + "&page=1")
      .then((res) => {
        if (res) {
          setMovies(res.data.Search)
        }
      });
  };

  //get details
  const getDetails = (e, id) => {
    e.preventDefault()

    setSelectedId(id)
    axios.get(api + apiKey + `&i=${id}`).then((res) => {
      if (res) {
        setMovieDetails(res.data)
        showModal()
      }
    })
  }

  //submit the title entered
  const handleSubmit = (e) => {
    e.preventDefault();
    getInfo();
  };

  return (
    <div>
      <form>
        <div className='searchBar'>
          <label htmlFor='name'></label>
          <input
            type='text'
            name='name'
            placeholder='movie name'
            onChange={(e) => setName(e.target.value)}
          />
          <button type='submit' onClick={(e) => handleSubmit(e)}>
            Search
          </button>
        </div>
      </form>

      {movies ? 
      <div className="movies">
        {movies.map(movie => (
          <div key={movie.imdbID} className="movie">
            <img src={movie.Poster} alt=""/>
            <div className="movie-title">
              <p>{movie.Title}</p>
            </div>
            <button className="movie-detailsBtn" 
            onClick={e => getDetails(e, movie.imdbID)}
            >Details</button>

            {/* modal */}
            {movieDetails && (selectedId===movie.imdbID) && show ? 
              <MovieModal/> : 
              <div className="modal display-none"></div>
            }

          </div>))}
      </div> 
      : null}
    </div>
  );
};

export default Main;
```

![Modal is working](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/92h7dlc5imrlfir6lkog.png)

Como podrás haber notado, no muestra la información y tampoco se puede cerrar, volvemos a `Main.js` y en la parte donde retornamos el modal vamos a pasar `$handleClose`, y los detalles con una propiedad que llamaremos `movieInfo`.

```js
{/* modal */}
{movieDetails && (selectedId===movie.imdbID) && show ? 
  <MovieModal 
  movieInfo={movieDetails} 
  handleClose={handleClose}/> : 
  <div className="modal display-none"></div>
}
```

Volvemos a nuestro `MovieModal.js`, pasaremos los `props` de la siguiente manera.

```js
const MovieModal = ({movieInfo, handleClose}) => {
  return(
    .
    .
    .
  )
}
export default MovieModal
```

Ahora modificamos el return para que devuelva algunos datos, (puedes pasar mas si lo deseas), y al botón de close haremos que ejecute la función `handleClose` cuando se le haga clic.


```js
const MovieModal = ({ movieInfo, handleClose }) => {
  return (
    <div className='modal display-block'>
      <section className='modal-main'>
        <div className='modal-body'>
          <div className='modal-img'>
            <img src={movieInfo.Poster} alt='Poster' />
          </div>
        </div>
        <div className='modal-info'>
          <p>
            <b>Actors:</b> {movieInfo.Actors}
          </p>
          <p>
            <b>Genre:</b> {movieInfo.Genre}
          </p>
          <p>
            <b>Director:</b> {movieInfo.Director}
          </p>
          <p>
            <b>Released:</b> {movieInfo.Released}
          </p>
          <p>
            <b>Plot:</b> {movieInfo.Plot}
          </p>
        </div>
        <button className='modal-closebtn' onClick={handleClose}>
          Close
        </button>
      </section>
    </div>
  );
};

export default MovieModal;
```

![modal with details](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bnlxxz45jb43ojan2ocj.png)

5. ## Paginación

Ahora que tenemos esa sección lista, crearemos la funcionalidad de paginación y asi poder ver mas resultados.

Vovlemos a nuestro componente Main.js, al realizar la peticion GET a la api nos devuelven un objeto con una propiedad llamada `totalResults`, esta propiedad será clave para crear la funcionalidad de paginación.


![total results](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vg15psxat6w1xijpylpk.png)

Lo primero que haremos será añadir un nuevo estado, luego iremos a nuestra función getInfo y la modificaremos para que actualice `totalResults` con los datos correspondientes

```js
const Main = () => {
  const [name, setName] = useState("");
  const [movies, setMovies] = useState([])
  const [selectedId, setSelectedId] = useState(null)
  const [movieDetails, setMovieDetails] = useState({})

  //modal
  const [show, setShow] = useState(false)

  //pagination
  const [totalResults, setTotalResults] = useState()
  .
  .
  .

  //get response from API
  const getInfo = () => {
    axios
      .get(api + apiKey + `&s=${name}` + "&type=movie" + "&page=1")
      .then((res) => {
        if (res) {
          setMovies(res.data.Search)
          setTotalResults(res.data.totalResults)
        }
      });
  };

  .
  .
  .
```

Con ayuda de `totalResults` podremos calcular el número de páginas que tendrá la busqueda que realicemos, crearemos otro estado `const [numberOfPages, setNumberOfPages] = useState()` y construiremos una función `getNumberOfPages` para obtener el número de páginas de nuestra busqueda.

En la función divideremos entre 10 porque solo obtenemos 10 resultados como máximo por página, por lo que usaremos el operador módulo para ver si la división arroja residuo, en caso de que arroje residuo, argegaremos una página adicional. usaremos `parseInt()` ya que `totalResults` es un string. Finalmente actualizaremos `numberOfPages` con el valor del número de páginas.


```js
.
.
.
//pagination
  const [totalResults, setTotalResults] = useState()
  const [numberOfPages, setNumberOfPages] = useState()
.
.
.

const getNumberOfPages = () => {
  if (totalResults % 10 > 0) {
    const numberOfpages = parseInt((totalResults / 10) + 1)
    setNumberOfPages(numberOfpages)
    return
  }
    const numberOfpages = parseInt(totalResults / 10)
    setNumberOfPages(numberOfpages)
}
```

Ahora crearemos un estado que se va a encargar de actualizarce con la página actual, que será la página que seleccionemos `const [currentPage, setCurrentPage] = useState()`

Modificaremos la función `getInfo()` de la siguiente manera para que cuando hagamos nuestra primera busqueda, actualice `currentPage` en 1, y empezaremos a mostrar los números de las páginas con la siguiente lógica después del return.

Si ya tenemos el número de páginas, entonces mostramos un div con las páginas, de lo contrario no lo renderizaremos. Como mostraremos las páginas enumeradas haremos lo siguiente, si la página anterior `currentPage -1` es igual a 0, no la mostrarémos, de lo contrario mostraremos `currentPage - 1`, luego la página actual, es decir `currentPage`, y por ultimo la página siguiente con `currentPage + 1` .


```js
.
.
.
//pagination
const [totalResults, setTotalResults] = useState()
const [numberOfPages, setNumberOfPages] = useState()
const [currentPage, setCurrentPage] = useState()
.
.
.

//get response from API
const getInfo = () => {
  axios
    .get(api + apiKey + `&s=${name}` + "&type=movie" + "&page=1")
    .then((res) => {
      if (res) {
        setMovies(res.data.Search);
        setTotalResults(res.data.totalResults);
        setCurrentPage(1)
      }
    });
};


return(
  {numberOfPages ? (
    <div className='pages'>
      {/* if prev page is 0 it wont show */}
      {currentPage - 1 === 0 ? null : (
        <b >{currentPage - 1}</b>
      )}
      <b  className='actualPage'>
        {currentPage}
      </b>
      <b >{currentPage + 1}</b>
    </div>
  ) : null}
)
 ```

![pagination](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d0s7m5epwwjkesii6898.png)

De momento solo podemos ver números, pero no tiene ninguna funcionalidad, hagámosla.

1- usaremos `useEffect()` para que ejecute `getNumbersOfPages()` .

2- Modificaremos nuestra función `getInfo()` y le pasaremos como argumento `pageNumber`, de tal manera de que si le pasamos `pageNumber` hará la petición GET a la api con el valor de `pageNumber` en el parametro de page, caso contrario nos devolvera el valor con el valor de la página en 1 como veniamos haciendo hasta ahora.

3- Crearemos un arreglo de páginas, el cual llenaremos con ayuda de un ciclo `for` que empezaremos en 1 e iterará el numero de veces correspondiente a `numberOfPages`, ejemplo (si el numero de páginas es 5, pasara 5 veces, y tendremos nuestro arreglo pages con 5 valores).

4- Crearemos una función `goTo(pageNumber)` que tendrá como argumento `pageNumber`, cada vez que se ejecute esta función actualizaremos `currentPage` con el valor de la página seleccionada, es decir `pageNumber`. Y luego se ejecutará `getInfo` con esa misma página que seleccionamos.

5- En la parte donde renderizamos nuestra paginación, haremos unas modificaciones pata que al hacer clic en el número de la página, ejecute la funcion `goTo` con la página que seleccionamos.

```js
.
.
.

//get response from API
const getInfo = (pageNumber) => {
  if (pageNumber) {
    axios
      .get(
        api + apiKey + `&s=${name}` + "&type=movie" + `&page=${pageNumber}`
      )
      .then((res) => {
        if (res) {
          setMovies(res.data.Search);
          setTotalResults(res.data.totalResults);
        }
      });
    return;
  }
  axios
    .get(api + apiKey + `&s=${name}` + "&type=movie" + "&page=1")
    .then((res) => {
      if (res) {
        setMovies(res.data.Search);
        setTotalResults(res.data.totalResults);
        setCurrentPage(1);
      }
    });
};

//getnumberOFpageseffect
useEffect(() => {
  getNumberOfPages();
});

const pages = [];

for (let i = 1; i <= numberOfPages; i++) {
  pages.push(<p key={i} onClick={e => goTo(i)}>{i}</p>)
}

const goTo = (pageNumber) => {

  setCurrentPage(pageNumber)
  getInfo(pageNumber)
  window.scrollTo(0, 0)
}


return(
  .
  .
  .
  {numberOfPages ? (
    <div className='pages'>
      {/* if prev page is 0 it wont show */}
      {currentPage - 1 === 0 ? null : <b onClick={e => goTo(currentPage-1)}>{currentPage - 1}</b>}
      <b onClick={e => goTo(currentPage)}className='actualPage'>{currentPage}</b>
      <b onClick={e => goTo(currentPage+1)}>{currentPage + 1}</b>
    </div>
  ) : null}
)
```

Finalmente, nuestro archivo debe verse así.

```js
import React, { useState, useEffect } from "react";
import axios from "axios";

//components
import MovieModal from "./MovieModal";

//api
const api = "https://www.omdbapi.com/?";

//api key
const apiKey = "apikey=18eaeb4f";

const Main = () => {
  const [name, setName] = useState("");
  const [movies, setMovies] = useState([]);
  const [selectedId, setSelectedId] = useState(null);
  const [movieDetails, setMovieDetails] = useState({});

  //modal
  const [show, setShow] = useState(false);

  //pagination
  const [totalResults, setTotalResults] = useState(0);
  const [numberOfPages, setNumberOfPages] = useState();
  const [currentPage, setCurrentPage] = useState();

  const getNumberOfPages = () => {
    if (totalResults % 10 > 0) {
      const numberOfpages = parseInt(totalResults / 10 + 1);
      setNumberOfPages(numberOfpages);
      return;
    }
    const numberOfpages = parseInt(totalResults / 10);
    setNumberOfPages(numberOfpages);
  };

  //modal config
  const showModal = () => {
    setShow(true);
  };

  const hideModal = () => {
    setShow(false);
    setMovieDetails();
  };

  const handleClose = () => {
    hideModal();
  };

  //get response from API
  const getInfo = (pageNumber) => {
    if (pageNumber) {
      axios
        .get(
          api + apiKey + `&s=${name}` + "&type=movie" + `&page=${pageNumber}`
        )
        .then((res) => {
          if (res) {
            setMovies(res.data.Search);
            setTotalResults(res.data.totalResults);
          }
        });
      return;
    }
    axios
      .get(api + apiKey + `&s=${name}` + "&type=movie" + "&page=1")
      .then((res) => {
        if (res) {
          setMovies(res.data.Search);
          setTotalResults(res.data.totalResults);
          setCurrentPage(1);
        }
      });
  };

  //get details
  const getDetails = (e, id) => {
    e.preventDefault();

    setSelectedId(id);
    axios.get(api + apiKey + `&i=${id}`).then((res) => {
      if (res) {
        setMovieDetails(res.data);
        showModal();
      }
    });
  };

  //submit the title entered
  const handleSubmit = (e) => {
    e.preventDefault();
    getInfo();
  };

  //getnumberOFpageseffect
  useEffect(() => {
    getNumberOfPages();
  });

  const pages = [];

  for (let i = 1; i <= numberOfPages; i++) {
    pages.push(
      <p key={i} onClick={(e) => goTo(i)}>
        {i}
      </p>
    );
  }

  const goTo = (pageNumber) => {
    setCurrentPage(pageNumber);
    getInfo(pageNumber);
    window.scrollTo(0, 0);
  };

  return (
    <div>
      <form>
        <div className='searchBar'>
          <label htmlFor='name'></label>
          <input
            type='text'
            name='name'
            placeholder='movie name'
            onChange={(e) => setName(e.target.value)}
          />
          <button type='submit' onClick={(e) => handleSubmit(e)}>
            Search
          </button>
        </div>
      </form>

      {movies ? (
        <div className='movies'>
          {movies.map((movie) => (
            <div key={movie.imdbID} className='movie'>
              <img src={movie.Poster} alt='' />
              <div className='movie-title'>
                <p>{movie.Title}</p>
              </div>
              <button
                className='movie-detailsBtn'
                onClick={(e) => getDetails(e, movie.imdbID)}
              >
                Details
              </button>

              {/* modal */}
              {movieDetails && selectedId === movie.imdbID && show ? (
                <MovieModal
                  movieInfo={movieDetails}
                  handleClose={handleClose}
                />
              ) : (
                <div className='modal display-none'></div>
              )}
            </div>
          ))}
        </div>
      ) : null}

      {numberOfPages ? (
        <div className='pages'>
          {/* if prev page is 0 it wont show */}
          {currentPage - 1 === 0 ? null : (
            <b onClick={(e) => goTo(currentPage - 1)}>{currentPage - 1}</b>
          )}
          <b onClick={(e) => goTo(currentPage)} className='actualPage'>
            {currentPage}
          </b>
          <b onClick={(e) => goTo(currentPage + 1)}>{currentPage + 1}</b>
        </div>
      ) : null}
    </div>
  );
};

export default Main;
```

6. ## Conclusión

En este post aprendimos a integrar una api a una aplicación de react de forma básica.

Realmente espero que hayas podido seguir el post sin problemas, y en caso de que no lo hayas podido hacer te pido disculpas, y que por favor me dejes tus dudas o comentarios.

Como mencioné anteriormente, la interfaz que creé para este ejemplo es muy sencilla, se puede mejorar asi como el código, te animo a que lo mejores y le agregues mas funcionalidades.

[Puedes contactarme por telegram si necesitas contratar a un desarrollador Full Stack.](https://t.me/rtagliajs)

También puedes contactarme por **discord Appu#9136**

[Puedes encontrar el repo aquí en caso de que lo desees clonar.](https://github.com/rtagliaviaz/react-omdb-tut)

Gracias por tu tiempo.