I have an "Inbox" page. Depending on the current screen size, I render either a mobile friendly version of the inbox or a desktop version.
Currently my page doesn't render the messages every time, I can see that it's due to my useEffect
Here's the Inbox component:
import { useEffect } from "react";
import { getUserConversations } from "@services/firebase/client/chat-client-services";
import userDataStore from "@stores/UserState/UserStore";
import InboxMessagePreview from "@components/Inbox/InboxMessagePreview/InboxMessagePreview";
import authStore from "@stores/AuthState/AuthStore";
import useSWR from "swr";
import Chat from "@components/Chat/Chat";
import Router, { useRouter } from "next/router";
import useWindowSize from "hooks/useWindowSize";
import { classNames } from "helpers/helpers";
import Skeleton from "@components/UI/Loading/Skeleton/Skeleton";
export default function Inbox() {
const size = useWindowSize();
const currentUser = authStore((state) => state.currentUser);
const userData = userDataStore((state) => state.userData);
const { data, error } = useSWR(currentUser?.uid, getUserConversations);
const router = useRouter();
console.log({ data });
console.log({ size });
useEffect(() => {
if (
!Router?.query?.chat &&
data?.conversations?.length > 0 &&
size.width >= 768
) {
console.log("IN USE EFFECT IF");
Router.push(
{
pathname: `/inbox`,
query: { chat: data.conversations[0].docID },
},
undefined,
{ shallow: true }
);
}
}, [data, size]);
if (error) {
<p>Error</p>;
}
if (!data) {
return <InboxSkeleton />;
}
if (size?.width < 768 && data) {
return (
<MobileChat
currentUser={currentUser}
data={data}
query={router?.query}
userData={userData}
/>
);
}
if (size?.width >= 768 && data) {
return (
<DesktopChat
currentUser={currentUser}
data={data}
query={router?.query}
userData={userData}
/>
);
}
return null;
}
The console log inside the useEffect does not fire sometimes on page load and therefore I can't see the console log and the messages do not load and a blank page is shown.
My guesses are either the useWindowSize()
hook or using Next's Router
.
The reason I am using both useRouter
and Router
is because I use Router
inside useEffects.
If I use router.push()
inside a useEffect
, React will warn me that it will need to be added to the dependency array. If I do this, the router
will be updated in the useEffect
and then it will therefore re-trigger, creating an infinite loop.
The useWindowSize
is as follows:
import { useState, useEffect } from "react";
// Define general type for useWindowSize hook, which includes width and height
interface Size {
width: number | undefined;
height: number | undefined;
}
function useWindowSize(): Size {
const [windowSize, setWindowSize] = useState<Size>({
width: undefined,
height: undefined,
});
useEffect(() => {
// Handler to call on window resize
function handleResize() {
// Set window width/height to state
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}
// Add event listener
window.addEventListener("resize", handleResize);
// Call handler right away so state gets updated with initial window size
handleResize();
// Remove event listener on cleanup
return () => window.removeEventListener("resize", handleResize);
}, []); // Empty array ensures that effect is only run on mount
return windowSize;
}
export default useWindowSize;
CodePudding user response:
inside your code you are using in the useEffect Router.push
instead of router.push()
CodePudding user response:
Figured out what was wrong.
I did not realise useSWR
keys are global. Since I am using the current users UID as the key here, it got data from another component elsewhere that uses the same key, therefore it was getting the wrong data.