Skip to content

Instantly share code, notes, and snippets.

@rmurati
Last active June 14, 2021 08:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmurati/6ee7a319f412f3d0b0c7f3dbb57b6d18 to your computer and use it in GitHub Desktop.
Save rmurati/6ee7a319f412f3d0b0c7f3dbb57b6d18 to your computer and use it in GitHub Desktop.
Container/View pattern in React inc. hooks
import composeHooks from "react-hooks-compose";
import { useUserData } from "@hooks/useUserData";
import Card from "@components/Card";
import CardContainer from "@containers/CardContainer"
// composing card with our hook
const ComposedCard = composeHooks({ useUserData })(Card);
const App = () => {
return (
<div className="app">
<ComposedCard />
<CardContainer />
</div>
);
};
export default App;
import style from "./Card.module.css";
const Card = ({ title, location, email, gender, image }) => (
<section className={style.card}>
<img
className={style.cardImage}
src={image}
alt={title}
/>
<div className={style.cardContent}>
<h3 className={style.cardTitle}>{title}</h3>
<span className={style.cardLocation}>{location}</span>
<div className={style.cardContact}>
<span className={style.cardMail}>{`email: ${email}`}</span>
<span className={style.cardGender}>{`gender: ${gender}`}</span>
</div>
</div>
</section>
);
export default Card;
.card {
display: flex;
align-self: center;
width: fit-content;
background: #ffffff;
box-shadow: 0px 2px 4px rgba(119, 140, 163, 0.06),
0px 4px 6px rgba(119, 140, 163, 0.1);
border-radius: 8px;
padding: 24px;
margin: 0 auto;
}
.cardImage {
height: 80px;
width: 80px;
border-radius: 100px;
}
.cardContent {
font-family: sans-serif;
line-height: 0;
margin-left: 20px;
}
.cardContact {
display: flex;
flex-direction: column;
}
.cardTitle {
font-size: 20px;
color: #112340;
margin-bottom: 20px;
}
.cardLocation {
font-size: 12px;
color: #112340;
margin-bottom: 22px;
opacity: 0.85;
}
.cardMail,
.cardGender {
font-size: 12px;
color: #112340;
margin-top: 15px;
opacity: 0.65;
}
import { useState, useEffect } from "react";
import axios from "axios";
import Card from "@components/Card";
const CardContainer = () => {
const [userData, setUserData] = useState(null);
useEffect(() => {
const fetchData = async () => {
const result = await axios("https://randomuser.me/api/");
const user = result.data.results[0];
setUserData({
gender: user.gender,
email: user.email,
location: `${user.location.city}, ${user.location.country}`,
title: `${user.name.title}. ${user.name.first} ${user.name.last}`,
image: user.picture.thumbnail,
});
};
fetchData();
}, []);
return (
<Card
title={userData?.title || "N/A"}
location={userData?.location || "N/A"}
email={userData?.email || "N/A"}
gender={userData?.gender || "N/A"}
image={userData?.image || ""}
/>
);
};
export default CardContainer;
import { useUserData } from '@hooks/useUserData';
import Card from "@componets/Card";
const UserCardContainer = () => {
const {
title,
location,
email,
gender,
image,
} = useUserData();
return (
<Card
title={title}
location={location}
email={email}
gender={gender}
image={image}
/>
);
};
export default UserCardContainer;
import { useState, useEffect } from "react";
import axios from "axios";
export const useUserData = () => {
const [userData, setUserData] = useState(null);
useEffect(() => {
const fetchData = async () => {
const result = await axios("https://randomuser.me/api/");
const user = result.data.results[0];
setUserData({
gender: user.gender,
email: user.email,
location: `${user.location.city}, ${user.location.country}`,
title: `${user.name.title}. ${user.name.first} ${user.name.last}`,
image: user.picture.thumbnail,
});
};
fetchData();
}, []);
return {
gender: userData?.gender || "N/A",
email: userData?.email || "N/A",
location: userData?.location || "N/A",
title: userData?.title || "N/A",
image: userData?.image || "",
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment