stream-chat-react icon indicating copy to clipboard operation
stream-chat-react copied to clipboard

Stream-chat-react: Redirecting to profile from user avatar in channel

Open AGSTRANGER opened this issue 10 months ago • 2 comments

Hello, I have implemented live chat using stream-chat-react. When the user clicks on the avatar he's talking with I need to redirect to that user's profile:

Image

I couldn't find a way to do this in the documentation.
Here's the relevant code:

    import { Button } from "@/components/ui/button";
    import { cn } from "@/lib/utils";
    import { Menu } from "lucide-react";
    import {
      Channel,
      ChannelHeader,
      ChannelHeaderProps,
      MessageInput,
      MessageList,
      Window,
    } from "stream-chat-react";
    
    interface ChatChannelProps {
      open: boolean;
      openSidebar: () => void;
    }
    
    export default function ChatChannel({ open, openSidebar }: ChatChannelProps) {
      return (
        <div className={cn("w-full md:block", !open && "hidden")}>
          <Channel>
            <Window>
              <CustomChannelHeader openSidebar={openSidebar} />
              <MessageList />
              <MessageInput />
            </Window>
          </Channel>
        </div>
      );
    }
    
    interface CustomChannelHeaderProps extends ChannelHeaderProps {
      openSidebar: () => void;
    }
    
    function CustomChannelHeader({
      openSidebar,
      ...props
    }: CustomChannelHeaderProps) {
      return (
        <div className="flex items-center gap-3">
          <div className="h-full p-2 md:hidden">
            <Button size="icon" variant="ghost" onClick={openSidebar}>
              <Menu className="size-5" />
            </Button>
          </div>
          <ChannelHeader {...props} />
        </div>
      );
    }


AGSTRANGER avatar Mar 24 '25 09:03 AGSTRANGER

Hello @AGSTRANGER , this sounds like a question how to implement redirect to another URL upon clicking on an HTML element. Is my understanding correct?

MartinCupela avatar Mar 27 '25 09:03 MartinCupela

Hello not really. I needed a way to:

  1. Detect on click in user avatar
  2. Find the other user's id

I managed to do this. Here's the solution in case anyone needs it:

CustomChatAvatar

    import { Avatar, AvatarProps, useChatContext } from "stream-chat-react";
    import { useRouter } from "next/navigation";
    import type { BaseSyntheticEvent } from "react";
    import { useSelector } from "react-redux";
    import { RootState } from "@/store/store";
    
    export default function CustomAvatar(props: AvatarProps) {
      const router = useRouter();
      const { channel } = useChatContext();
    
      const {
        loading: connectedUserLoading,
        error: connectedUserError,
        data: connectedUserData,
      } = useSelector((state: RootState) => state.users.connectedUser);
      let otherUserId: string | undefined = undefined;
      if (channel) {
    
        const currentUserId = connectedUserData?._id;
    
        if (currentUserId) {
          const otherUser = Object.values(channel.state.members).find(
            (member) => member.user_id !== currentUserId,
          );
    
          if (otherUser) {
            otherUserId = otherUser.user_id;
          }
        }
      }
    
      const handleClick = (event: BaseSyntheticEvent) => {
        event.stopPropagation(); // Prevents triggering parent handlers
        if (otherUserId) {
          router.push(`/users/${otherUserId}`);
        }
      };
    
      return <Avatar {...props} onClick={handleClick} />;
    }

Then I used that here:

ChatChannel

    import { Button } from "@/components/ui/button";
    import { cn } from "@/lib/utils";
    import { Menu } from "lucide-react";
    import {
      Channel,
      ChannelHeader,
      ChannelHeaderProps,
      MessageInput,
      MessageList,
      Window,
    } from "stream-chat-react";
    import CustomAvatar from "@/components/CustomChatAvatar";
    interface ChatChannelProps {
      open: boolean;
      openSidebar: () => void;
    }
    
    export default function ChatChannel({ open, openSidebar }: ChatChannelProps) {
      return (
        <div className={cn("w-full md:block", !open && "hidden")}>
          <Channel>
            <Window>
              <CustomChannelHeader openSidebar={openSidebar} />
              <MessageList />
              <MessageInput />
            </Window>
          </Channel>
        </div>
      );
    }
    
    interface CustomChannelHeaderProps extends ChannelHeaderProps {
      openSidebar: () => void;
    }
    
    function CustomChannelHeader({
      openSidebar,
      ...props
    }: CustomChannelHeaderProps) {
      console.log("🚀 ~ CustomChannelHeader props:", props);
    
      return (
        <div className="flex items-center gap-3">
          <div className="h-full p-2 md:hidden">
            <Button size="icon" variant="ghost" onClick={openSidebar}>
              <Menu className="size-5" />
            </Button>
          </div>
          <ChannelHeader {...props} Avatar={CustomAvatar} />
        </div>
      );
    }


AGSTRANGER avatar Mar 27 '25 11:03 AGSTRANGER