We often work with lots of designs about user profiles, and in some situations we need to fetch information about the user and render the avatar stablished, but in some cases it can be an empty string and we need to generate an avatar with the user's first letter of their first name
and last name
.
You can see the final result here: View link
API & React Hook
We are going to use this API to fetch the names and filter the information to just use the names and return 20 results like this:
https://randomuser.me/api/?inc=name&results=20
After this we are going to create a react hook to fetch the information using the fetch API. But first, let's create a folder called hooks
in the root of the project and a file called constants
to store the endpoint and keep everything organize.
import { useEffect, useState } from "react";
import { API_ENDPOINT } from "../constants";
export const useData = () => {
const [userNames, setUserNames] = useState([]);
useEffect(() => {
fetch(API_ENDPOINT)
.then((res) => res.json())
.then((data) => setUserNames(data.results));
.catch((error) => console.log(error))
}, []);
return {
userNames
};
};
Then, we can go to our App.js
file and import the hook and render the names.
import { useData } from "./hooks/useData";
export default function App() {
const { userNames } = useData();
return (
<div className="App">
{userNames.map(({ name }) => (
<p key={name.first}>{name.first}</p>
))}
</div>
);
}
Components
We are going to create two components for this project:
- UserCard: This will render the card element with the user info and avatar
-
UserPlaceHolder: this will render the circle with the user's first letters of their
first name
andlast name
User Card component
import UserPlaceHolder from "./UserPlaceholder";
const UserCard = ({ first, last }) => {
let username = `${first} ${last}`;
return (
<div className="user">
<UserPlaceHolder name={username} />
<p className="user__name">{username}</p>
</div>
);
};
export default UserCard;
UserPlaceHolder Component
import {
generatePlaceholderName,
generateRandomColorNumber
} from "../../utils";
const UserPlaceHolder = ({ name }) => {
const userPlaceholder = generatePlaceholderName(name);
const placeholderBackground = `hsl(${generateRandomColorNumber()}, 50% , 50%)`;
return (
<div
className="user__placeholder"
style={{
backgroundColor: placeholderBackground
}}
>
{userPlaceholder}
</div>
);
};
export default UserPlaceHolder;
Note:
As we are using Plain CSS, the best approach to create a dynamic background color is with the style pro in the element. Other solutions are:
- Sass
- CSS in JS (Styled components, emotion)
Notice that in the UserPlaceHolder
component we are importing two functions from a utils folder that are:
-
generatePlaceholderName: function that receives user name and returns the first letter of the
first name
andlast name
; - generateRandomColorNumber: function that returns a number between 0 to 360 to use it in the HSL hue property of the style prop. This helps generate a dynamic background for each card;
export function generateRandomColorNumber() {
let randomHue = Math.floor(Math.random() * 360);
return randomHue;
}
export function generatePlaceholderName(name) {
//Split name by the space
let splitUsername = name.split(" "),
/* we validate if the data comes correctly with optional chaining. In the worst case, we
return a empty string*/
firstLetter = splitUsername[0]?.[0] ?? "",
secondletter = splitUsername[1]?.[0] ?? "";
return `${firstLetter}${secondletter}`;
}
CSS š§āāļø
After explaining the components and functionality, we need some CSS magic
:root {
--body-bg: #f3f4fa;
--card-border: #dcdce0;
}
body {
min-height: 100vh;
background-color: var(--body-bg);
max-width: 1200px;
margin-left: auto;
margin-right: auto;
}
.App {
font-family: sans-serif;
text-align: center;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 1.5rem;
justify-content: center;
}
.user {
border: 1px solid var(--card-border);
padding: 1rem;
width: 100%;
max-width: 180px;
border-radius: 0.5rem;
background-color: white;
}
.user__name {
font-weight: bold;
}
.user__placeholder {
width: 32px;
height: 32px;
margin-left: auto;
margin-right: auto;
padding: 0.5rem;
display: grid;
color: white;
place-items: center;
border-radius: 50%;
}
Last Step
Finally, we import UserCard to render the information and see component in action:
export default function App() {
const { userNames } = useData();
return (
<div className="App">
{userNames.map(({ name }) => (
<UserCard key={name.first} first={name.first} last={name.last} />
))}
</div>
);
}
Conclusion
Hope you find it useful for your projects. This is my first article and there are more to come. Happy coding!
Top comments (0)