Skip to content

Commit

Permalink
feat: useGetProfile hook
Browse files Browse the repository at this point in the history
instead of the UserProfileContext the hook will return an initial value, which may be undefined, but update it later

the profiles are stored in a global variable, so all calls to the hook share the same user profiles
  • Loading branch information
6lr61 committed Sep 13, 2024
1 parent 49b7019 commit e1d685d
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 97 deletions.
11 changes: 2 additions & 9 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { useContext } from "react";
import { AuthStateContext } from "./contexts/auth-state/AuthStateContext";
import LoginButton from "./components/LoginButton";
import { useTwitchChat } from "./hooks/useTwitchChat";
import Message from "./components/Message";
import MessageContainer from "./components/MessageContainer";
import Chat from "./components/Chat";

export default function App() {
const authContext = useContext(AuthStateContext);
const messages = useTwitchChat();

if (!authContext) {
return <p>Missing AuthStateContext provider?</p>;
Expand All @@ -23,11 +20,7 @@ export default function App() {
</p>
<article>
<h2>Chat Messages:</h2>
<MessageContainer messages={messages}>
{messages.map((message) => (
<Message key={message.message_id} message={message} />
))}
</MessageContainer>
<Chat />
</article>
</section>
)}
Expand Down
18 changes: 9 additions & 9 deletions src/components/MessageContainer.tsx → src/components/Chat.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { useEffect, useRef } from "react";
import type { ChatMessage } from "../hooks/useTwitchChat";
import TwitchBadgeProvider from "../contexts/badges/TwitchBadgeProvider";
import { useTwitchChat } from "../hooks/useTwitchChat";
import Message from "./Message";

export default function MessageContainer({
children,
messages,
}: {
children: React.ReactNode;
messages: ChatMessage[];
}): React.ReactElement {
export default function Chat(): React.ReactElement {
const messages = useTwitchChat();
const ref = useRef<HTMLDivElement>(null);

useEffect(() => {
Expand All @@ -22,7 +18,11 @@ export default function MessageContainer({
return (
<section ref={ref} className="h-[600px] justify-end overflow-y-auto">
<TwitchBadgeProvider>
<article className="flex flex-col gap-1">{children}</article>
<article className="flex flex-col gap-1">
{messages.map((message) => (
<Message key={message.message_id} message={message} />
))}
</article>
</TwitchBadgeProvider>
</section>
);
Expand Down
39 changes: 18 additions & 21 deletions src/components/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import Reply from "./Reply";
import TextSegment from "./TextSegment";
import TwitchEmote from "./TwitchEmote";
import UserName from "./UserName";
import UserProfileProvider from "../contexts/UserProfileProvider";

interface Props {
message: ChatMessage;
Expand Down Expand Up @@ -47,26 +46,24 @@ function fragmentToComponent(

export default function Message({ message }: Props): React.ReactElement {
return (
<UserProfileProvider login={message.chatter_user_login}>
<article className="flex flex-row gap-1">
<ProfilePicture />
<section className="flex-1 overflow-hidden rounded-md">
<header
className="flex px-2 gap-2 items-center bg-black/25"
style={{ backgroundColor: colorToRgba(message.color) }}
>
<BadgeList badges={message.badges} />
<UserName message={message} />
<ElapsedTime startingDate={message.timestamp} />
</header>
{message.reply && <Reply message={message.reply} />}
<section className="h-full bg-slate-800 break-words px-2 py-1">
{message.message.fragments.map((fragment, index) =>
fragmentToComponent(fragment, index)
)}
</section>
<article className="flex flex-row gap-1">
<ProfilePicture login={message.chatter_user_login} />
<section className="flex-1 overflow-hidden rounded-md">
<header
className="flex px-2 gap-2 items-center bg-black/25"
style={{ backgroundColor: colorToRgba(message.color) }}
>
<BadgeList badges={message.badges} />
<UserName message={message} />
<ElapsedTime startingDate={message.timestamp} />
</header>
{message.reply && <Reply message={message.reply} />}
<section className="h-full bg-slate-800 break-words px-2 py-1">
{message.message.fragments.map((fragment, index) =>
fragmentToComponent(fragment, index)
)}
</section>
</article>
</UserProfileProvider>
</section>
</article>
);
}
17 changes: 11 additions & 6 deletions src/components/ProfilePicture.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { useContext } from "react";
import { UserProfileContext } from "../contexts/UserProfileContext";
import { useGetProfile } from "../hooks/useGetProfile";

export default function ProfilePicture(): React.ReactElement {
const userData = useContext(UserProfileContext);
export default function ProfilePicture({
login,
}: {
login: string;
}): React.ReactElement {
const userData = useGetProfile(login);

return (
<article className="size-14 rounded-xl overflow-hidden bg-slate-700">
{userData?.profile_image_url && (
<article className="size-14 rounded-xl overflow-hidden">
{userData?.profile_image_url ? (
<img className="object-fill" src={userData.profile_image_url} />
) : (
<div className="bg-slate-600 size-full"></div>
)}
</article>
);
Expand Down
4 changes: 0 additions & 4 deletions src/contexts/UserProfileContext.ts

This file was deleted.

48 changes: 0 additions & 48 deletions src/contexts/UserProfileProvider.tsx

This file was deleted.

35 changes: 35 additions & 0 deletions src/hooks/useGetProfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useContext, useEffect, useState } from "react";
import { AuthStateContext } from "../contexts/auth-state/AuthStateContext";
import { getUser, type UserData } from "../utils/api/getUser";

const usersData = new Map<string, UserData>();

export function useGetProfile(login: string) {
const authStateContext = useContext(AuthStateContext);
const authState = authStateContext?.authState;

const [userProfile, setUserProfile] = useState<UserData | undefined>(() =>
usersData.get(login)
);

useEffect(() => {
if (usersData.has(login)) {
return;
}

if (!authState) {
return;
}

getUser(authState.token.value, authState.client.id, login)
.then((data) => {
usersData.set(login, data);
setUserProfile(() => data);
})
.catch((error: unknown) => {
console.error("UserProfile:", error);
});
}, [authState, login]);

return userProfile;
}

0 comments on commit e1d685d

Please sign in to comment.