Skip to content

Commit

Permalink
[Feature] Custom Hooks Implementation #8
Browse files Browse the repository at this point in the history
- useCurrentState
- useDebounceSearch
- useDefaultMovies
- useFilter
- useLoading
- useSearch
  • Loading branch information
Nyumat committed Jan 20, 2023
1 parent f6f8ee6 commit 3f4d8b5
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 0 deletions.
28 changes: 28 additions & 0 deletions hooks/useCurrentState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from "react";
import { useEffect } from "react";

interface CurrentStateProps {
filter: string[];
searchTerm: string;
}

const useCurrentState = ({ filter, searchTerm }: CurrentStateProps) => {
const [currentState, setCurrentState] = React.useState<string>("all");
useEffect((): any => {
if (filter.length <= 1 && searchTerm.length <= 1) {
setCurrentState("all");
}

if (filter.length > 1) {
setCurrentState("filter");
}

if (searchTerm.length > 0) {
setCurrentState("search");
}
}, [filter, searchTerm]);

return { currentState };
};

export default useCurrentState;
17 changes: 17 additions & 0 deletions hooks/useDebounceSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useState, useEffect } from "react";

export default function useDebounceSearch<T>(value: T, delay: number): T {
const [debouncedSearch, setDebouncedString] = useState(value);

useEffect(() => {
const handler = setTimeout(() => {
setDebouncedString(value);
}, delay);

return () => {
clearTimeout(handler);
};
}, [value, delay]);

return debouncedSearch;
}
25 changes: 25 additions & 0 deletions hooks/useDefaultMovies.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { useEffect } from "react";
import { Movie } from "../typings";
const useDefaultMovies = (page: number) => {
const [defaultData, setData] = React.useState<Movie[]>([]);
const [defaultLoading, setLoading] = React.useState(true);
const [defaultError, setError] = React.useState(false);
const [totalPages, setTotalPages] = React.useState(0);

useEffect(() => {
fetch(`/api/movies?page=${page}`)
.then((res) => res.json())
.then((data) => {
setData(data.movies);
setTotalPages(data.total_pages);
setLoading(false);
})
.catch((err) => {
setError(true);
});
}, [page]);

return { defaultData, defaultLoading, defaultError, totalPages };
};

export default useDefaultMovies;
44 changes: 44 additions & 0 deletions hooks/useFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useState, useEffect } from "react";
import { Movie, TvShow } from "../typings";
import axios from "axios";

interface FilterHookProps {
filter: string[];
}

type Data = {
filter_data: Movie[] | TvShow[];
};

const useFilter = ({ filter }: FilterHookProps) => {
let parsedFilterString = filter.join(",").substring(1);
const [filterData, setData] = useState<Data>({ filter_data: [] });
const [filterLoading, setIsLoading] = useState(false);
const [filterError, setError] = useState(false);
const [page, setPage] = useState(1);

useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
try {
const result = await axios(`/api/filter`, {
params: {
filter: parsedFilterString,
page: page,
},
});
setData(result.data);
} catch (error) {
setError(true);
} finally {
setIsLoading(false);
}
};

fetchData();
}, [parsedFilterString]);

return { filterData, filterLoading, filterError };
};

export default useFilter;
27 changes: 27 additions & 0 deletions hooks/useLoading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";

interface useLoadingProps {
filterLoading: boolean;
searchLoading: boolean;
defaultLoading: boolean;
}

const useLoading = ({
filterLoading,
searchLoading,
defaultLoading,
}: useLoadingProps) => {
const [isLoaded, setIsLoaded] = React.useState(false);

React.useEffect(() => {
if (filterLoading || searchLoading || defaultLoading) {
setIsLoaded(false);
} else {
setIsLoaded(true);
}
}, [filterLoading, searchLoading, defaultLoading]);

return isLoaded;
};

export default useLoading;
52 changes: 52 additions & 0 deletions hooks/useSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useState, useEffect } from "react";
import { Movie } from "../typings";
import useDebounceSearch from "./useDebounceSearch";
import axios from "axios";

interface useSearchProps {
search: string;
}

const useSearch = ({ search }: useSearchProps) => {
const debouncedSearch = useDebounceSearch(search, 800);
const [searchLoading, setLoading] = useState<boolean>(false);
const [searchData, setSearchData] = useState<Movie[]>([]);
const [totalPages, setTotalPages] = useState<number>(0);
const [page, setPage] = useState<number>(1);
const [searchError, setError] = useState<boolean>(false);

useEffect(() => {
if (debouncedSearch.length === 0) {
setLoading(false);
setSearchData([]);
}

if (debouncedSearch) {
setLoading(true);
axios
.get(`/api/search`, {
params: {
query: search,
page: page,
},
})
.then((res) => {
let data = res.data.search_data.filter((item: Movie) => {
return item.poster_path !== null && item.vote_average !== 0;
});
setTimeout(() => {
setLoading(false);
setSearchData(data);
setTotalPages(res.data.total_pages);
}, 1000);
})
.catch((err) => {
setError(true);
});
}
}, [debouncedSearch, page]);

return { searchLoading, searchData, totalPages, page, setPage, searchError };
};

export default useSearch;

0 comments on commit 3f4d8b5

Please sign in to comment.