How To Create A Profile Iterator Custom Hook With React and TypeScript
Final code
useProfileIterator.ts
import { useEffect, useState } from "react";
import axios from "axios";
export type User = {
name: string,
thumbnail: string,
age: number,
phone: string,
email: string
}
type Function = () => void;
const useProfileIterator = (url: string) : [User, boolean, Function, Function] => {
const [users, setUsers] = useState<User[]>([]);
const [index, setIndex] = useState(0);
const [loading, setLoading] = useState(false);
const fetchUser = async () => {
try {
setLoading(true);
const {data} = await axios.get(url);
if(data.results && data.results[0]){
setUsers(prevUsers => {
const user = data.results[0];
return [
...prevUsers,
{
name: `${user.name.title} ${user.name.first} ${user.name.last}`,
age: user.dob.age,
phone: user.phone,
email: user.email,
thumbnail: user.picture.medium
}
]
});
return true;
}
} catch (error) {
console.log(error);
}
finally{
setLoading(false);
}
}
const previous = () => {
if(index > 0) setIndex(prev => prev - 1);
}
const next = () => {
if(index < users.length - 1){
setIndex(prev => prev + 1);
return;
}
fetchUser().then(res => setIndex(prev => prev + 1));
}
useEffect(() => {
fetchUser();
}, []);
return [users[index], loading, previous, next];
}
export default useProfileIterator;
Users.tsx
import React from 'react'
import useProfileIterator, { User } from '../hooks/useProfileIterator'
import './Users.css'
const Users = () => {
const [user, loading, previous, next] = useProfileIterator('https://randomuser.me/api');
return (
<div className='UserContainer'>
{
loading ? <Loader />
: <Card user={user} />
}
<div className='controls'>
<button className='previous' onClick={previous}>Previous</button>
<button className='next' onClick={next}>Next</button>
</div>
</div>
)
}
type UserProps = {
user: User
}
const Card = ({user} : UserProps) => (
<div className='Card'>
<div className='topBG'></div>
<div className='content'>
<div className='imgContainerBG'>
<div className='imgContainer'>
<img src={user?.thumbnail} alt={user?.name} />
</div>
</div>
<div className='infos'>
<span className='fullName'>{user?.name}</span>
<span className='age'>{user?.age} years</span>
</div>
<div className='phone'>{user?.phone}</div>
<div className='email'>{user?.email}</div>
</div>
</div>
)
const Loader = () => (
<div className='Card Loader'>
<div className='topBG'></div>
<div className='content'>
<div className='imgContainerBG'>
<div className='imgContainer value'>
</div>
</div>
<div className='infos'>
<span className='fullName value'></span>
<span className='age value'></span>
</div>
<div className='phone value'></div>
<div className='email value'></div>
</div>
</div>
)
export default Users
Users.css
body{
background-color: #d6e5fe;
}
.UserContainer{
max-width: 300px;
margin: auto;
}
.Card{
height: 270px;
background-color: #fff;
border-radius: 15px;
margin-bottom: 15px;
overflow: hidden;
box-shadow: 0 2px 5px 1px rgb(64 60 67 / 16%);
display: flex;
flex-direction: column;
}
.Card .topBG{
height: 80px;
background-color: #514bb6;
}
.Card .content{
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 15px;
padding-top: 60px;
align-items: center;
position: relative;
}
.Card .content .imgContainerBG{
position: absolute;
width: 80px;
height: 80px;
border-radius: 50%;
background-color: #fff;
padding: 5px;
top: 0;
left: 50%;
transform: translate(-50%, -50%);
}
.Card .content .imgContainer{
width: 100%;
height: 100%;
border-radius: 50%;
overflow: hidden;
}
.Card .content .imgContainer img{
width: 100%;
}
.Card .content .infos{
display: flex;
justify-content: space-between;
width: 100%;
}
.Card .content .infos .fullName{
font-weight: bold;
max-width: 180px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.Card .content .infos .age{
color: gray;
max-width: 70px;
}
.controls{
background-color: #fff;
border-radius: 15px;
box-shadow: 0 2px 5px 1px rgb(64 60 67 / 16%);
display: flex;
justify-content: space-between;
padding: 15px;
}
.controls button{
background-color: #fff;
cursor: pointer;
padding: 5px 20px;
border-radius: 15px;
}
.controls .next{
color: #514bb6;
border: 2px solid #514bb6;
}
.controls .next:hover{
background-color: #514bb6;
color: #fff;
}
.controls .previous{
color: #ffa800;
border: 2px solid #ffa800;
}
.controls .previous:hover{
background-color: #ffa800;
color: #fff;
}
.Loader .value{
animation-duration: 2.2s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: shimmer;
animation-timing-function: linear;
background: linear-gradient(to right, #F6F6F6 8%, #F0F0F0 18%, #F6F6F6 33%);
background-size: 1200px 100%;
height: 12px;
width: 80%;
border-radius: 8px;
}
@keyframes shimmer {
0% {
background-position: -1200px 0;
}
100% {
background-position: 1200px 0;
}
}
Popular Tools
Recent Posts
Susan Wojcicki: The Garage Owner Who Shaped the History of Google
September 7, 2024
How To Create A Profile Iterator Custom Hook With React and TypeScript
September 7, 2024
How To Create a CSS Skeleton Animation in React js
November 19, 2022
How To Create a React Week Picker Using React Suite DatePicker?
November 13, 2022