From 61ed1d2af8e0477592170f04f0a50bfb6e3db50e Mon Sep 17 00:00:00 2001 From: Gil Teitelbaum Date: Thu, 17 Sep 2020 09:52:55 +0300 Subject: [PATCH] move to using hooks --- src/components/movieDetails.jsx | 27 ++---- src/components/movies.jsx | 135 ++++++++++++++--------------- src/components/moviesTable.jsx | 39 ++++----- src/components/titleAndContent.jsx | 2 +- src/services/restService.js | 4 +- 5 files changed, 91 insertions(+), 116 deletions(-) diff --git a/src/components/movieDetails.jsx b/src/components/movieDetails.jsx index 10348b6..857918d 100644 --- a/src/components/movieDetails.jsx +++ b/src/components/movieDetails.jsx @@ -5,7 +5,6 @@ import { Row, Col } from "react-bootstrap"; import { Link } from "react-router-dom"; import TitleAndContent from "./titleAndContent"; - class MovieDetails extends Component { constructor(props) { super(props); @@ -59,31 +58,23 @@ class MovieDetails extends Component { - - {movie.Rated} - - - {movie.Runtime} - - - {movie.Genre} - + {movie.Rated} + {movie.Runtime} + {movie.Genre}
- - {movie.Plot} - + {movie.Plot} - {this.displayTitledDataWithLine("Writer:", movie.Writer)} + - {this.displayTitledDataWithLine("Awards:", movie.Awards)} + - {this.displayTitledDataWithLine("Box Office:", movie.BoxOffice)} + @@ -94,8 +85,6 @@ class MovieDetails extends Component { ); } - } -export default MovieDetails; - +export default MovieDetails; \ No newline at end of file diff --git a/src/components/movies.jsx b/src/components/movies.jsx index 782ed44..a49a8a6 100644 --- a/src/components/movies.jsx +++ b/src/components/movies.jsx @@ -1,4 +1,4 @@ -import React, { Component } from "react"; +import React, { Component, useState } from "react"; import MoviesTable from "./moviesTable"; import restService from '../services/restService'; import config from "../config.json"; @@ -6,89 +6,86 @@ import { Form, Row, Col } from "react-bootstrap"; import { toast } from 'react-toastify'; -class Movies extends Component { - constructor(props) { - super(props); - this.state = { - movies: [], - totalMovies: 0, - isLoading: false, - didSearch: false, - movieSearchName: null, - movieYear: null, - lastPage: 1, - errors: {} - } - } +export default function Movies(props) { + const [movies, setMovies] = useState([]); + const [totalMovies, setTotalMovies] = useState(0); + const [isLoading, setIsLoading] = useState(false); + const [didSearch, setDidSearch] = useState(false); + const [movieSearchName, setMovieSearchName] = useState(null); + const [movieYear, setMovieYear] = useState(null); + const [lastPage, setLastPage] = useState(1); + const [errors, setErrors] = useState([]); - validate() { - const errors = {}; - const { movieSearchName, movieYear } = this.state; + function validate() { + const validationErrors = {}; - if (movieSearchName.trim() === '') - errors.movieSearchName = "Name of movie is required"; + if (!movieSearchName || movieSearchName.trim() === '') + validationErrors.movieSearchName = "Name of movie is required"; if (movieYear && movieYear.trim().length > 0 && isNaN(parseInt(movieYear.trim()))) { - errors.movieYear = "Year is invalid"; + validationErrors.movieYear = "Year is invalid"; } - return errors; + + return validationErrors; } - handleSubmit = event => { + const handleSubmit = event => { event.preventDefault(); - const errors = this.validate(); - this.setState({ errors }); - for (let key in errors) { - toast.error(errors[key]); + const validationErrors = validate(); + setErrors(validationErrors); + for (let key in validationErrors) { + toast.error(validationErrors[key]); return; // return on first error } - if (this.state.movieSearchName) { - this.performSearch(1) + if (movieSearchName) { + performSearch(1) } } - getMoreMovies = event => { - this.performSearch(this.state.lastPage + 1); + const getMoreMovies = event => { + performSearch(lastPage + 1); } - getUrl(page) { - let url = config.endpointBase + '&s=' + this.state.movieSearchName; - if (this.state.movieYear) - url += "&y=" + this.state.movieYear; + function getUrl(page) { + let url = config.endpointBase + '&s=' + movieSearchName; + if (movieYear) + url += "&y=" + movieYear; if (page > 1) url += "&page=" + page; return url; } - - async performSearch(page) { + async function performSearch(page) { try { - this.setState({ isLoading: true }); - const moviesRetrieved = await restService.get(this.getUrl(page)); - if (page > 1) - this.setState({ movies: this.state.movies.concat(moviesRetrieved.data.Search), totalMovies: moviesRetrieved.data.totalResults }); + setIsLoading(true); + const moviesRetrieved = await restService.get(getUrl(page)); + if (page > 1) { + let holdMovies = movies.concat(moviesRetrieved.data.Search); + setMovies(holdMovies); + } else - this.setState({ movies: moviesRetrieved.data.Search, totalMovies: moviesRetrieved.data.totalResults }); - this.setState({ isLoading: false, lastPage: page, didSearch: true }); + setMovies(moviesRetrieved.data.Search); + setTotalMovies(moviesRetrieved.data.totalResults); + setIsLoading(false); + setDidSearch(true); + setLastPage(page); } catch (ex) { - this.setState({ isLoading: false }); + setIsLoading(false); if (ex.response && ex.response.status === 404) { alert("not found") } } } - handleChange = event => { - const { id, value } = event.target; - this.setState(prevState => ({ - ...prevState, - [id]: value - })); + const handleTitleChange = event => { + setMovieSearchName(event.target.value); } - showMovies() { - const { totalMovies, movies } = this.state; + const handleYearChange = event => { + setMovieYear(event.target.value); + } + function showMovies() { return (
@@ -99,24 +96,18 @@ class Movies extends Component { ); } - render() { - const { isLoading, movies, totalMovies, movieSearchName, movieYear } = this.state; - - return ( - <> - {isLoading &&

Loading...

} -
- - - - - -
- {this.state.didSearch ? this.showMovies() : null} - {movies && movies.length > 0 && movies.length < totalMovies ? : null} - - ); - } + return ( + <> + {isLoading &&

Loading...

} +
+ + + + + +
+ {didSearch ? showMovies() : null} + {movies && movies.length > 0 && movies.length < totalMovies ? : null} + + ); } - -export default Movies; diff --git a/src/components/moviesTable.jsx b/src/components/moviesTable.jsx index 36401c4..35e1a29 100644 --- a/src/components/moviesTable.jsx +++ b/src/components/moviesTable.jsx @@ -1,27 +1,22 @@ -import React, { Component } from "react"; +import React from "react"; import { Link } from "react-router-dom"; -class MoviesTable extends Component { - render() { - const { movies } = this.props; - - return ( -
- {movies.map(movie => ( -
- - {"Movie -

{movie.Title} {"(" + movie.Year + ")"}

- -
- ))} -
- ); - } - - setDefaultSource(event) { +export default function MoviesTable(props) { + function setDefaultSource(event) { event.target.src = "../../noimage.png"; } -} + const { movies } = props; -export default MoviesTable; + return ( +
+ {movies.map(movie => ( +
+ + {"Movie +

{movie.Title} {"(" + movie.Year + ")"}

+ +
+ ))} +
+ ); +} \ No newline at end of file diff --git a/src/components/titleAndContent.jsx b/src/components/titleAndContent.jsx index 84f2838..4c1c5c1 100644 --- a/src/components/titleAndContent.jsx +++ b/src/components/titleAndContent.jsx @@ -1,10 +1,10 @@ import React from "react"; import { Row, Col } from "react-bootstrap"; - export default function TitleAndContent(props) { return ( <> + {props.displayLine &&
} {props.title} diff --git a/src/services/restService.js b/src/services/restService.js index 55ad5da..c4de1ed 100644 --- a/src/services/restService.js +++ b/src/services/restService.js @@ -1,10 +1,10 @@ import axios from 'axios'; import { toast } from 'react-toastify'; -import logger from "./loggerService"; +import { error } from "./loggerService"; axios.interceptors.response.use(null, error => { if (!error.response || error.response.status < 400 || error.response.status >= 500) { - logger.error("Error getting movies from server - " + error); + error("Error getting movies from server - " + error); toast.error("an unexpected error happened"); } return Promise.reject(error);