DEV Community

Cover image for Creating an avatar based in the user name with React
Juan Carlos Cruz
Juan Carlos Cruz

Posted on • Originally published at jcruz.hashnode.dev

Creating an avatar based in the user name with React

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
  };
};
Enter fullscreen mode Exit fullscreen mode

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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 and last 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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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 and last 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}`;
}
Enter fullscreen mode Exit fullscreen mode

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%;
}
Enter fullscreen mode Exit fullscreen mode

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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)