我的使用效果在预期时不会发射

发布于 2025-02-13 03:34:17 字数 3523 浏览 1 评论 0原文

我有一个“收件箱”页面。根据当前的屏幕尺寸,我呈现收件箱的移动友好版本或桌面版本。

目前,我的页面并非每次都呈现消息,我可以看到这是由于我的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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暖阳 2025-02-20 03:34:17

在您的代码中,您在使用router.push而不是router.push()中使用的代码中。

inside your code you are using in the useEffect Router.push instead of router.push()

雨落□心尘 2025-02-20 03:34:17

弄清楚了什么问题。

我没有意识到使用密钥是全局。由于我将当前用户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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文