我的使用效果在预期时不会发射
我有一个“收件箱”页面。根据当前的屏幕尺寸,我呈现收件箱的移动友好版本或桌面版本。
目前,我的页面并非每次都呈现消息,我可以看到这是由于我的useffect
这是Inbox组件:
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;
}
在Page Load上使用使用效率内的控制台log不会发射,因此我可以't请参阅控制台日志,并显示消息未加载,并显示空白页。
我的猜测是usewindowsize()
钩子,或者使用Next的Router
。
我同时使用userOuter
和路由器
是因为我使用路由器
在使用eSuseFects中。 如果我在使用
使用 usefeft 中使用router.push(),React会警告我,它需要将其添加到依赖项数组中。如果我这样做,
路由器
将在useffect
中更新,然后将重新触发,创建一个无限的循环。
useWindowsize
如下:
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;
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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在您的代码中,您在使用
router.push
而不是router.push()
中使用的代码中。inside your code you are using in the useEffect
Router.push
instead ofrouter.push()
弄清楚了什么问题。
我没有意识到
使用
密钥是全局。由于我将当前用户UID用作这里的密钥,因此它从其他地方使用相同密钥的另一个组件中获取数据,因此它获取了错误的数据。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.