首页  >  问答  >  正文

React/Next 更新状态并在 useEffect 之后重置它

我正在尝试从 api 流式传输数据,但是在渲染期间,useEffect 被多次调用,其中在初始页面加载期间,除了被多次调用之外,一切都工作正常,但是当我刷新时在浏览器中的页面上,也会发生同样的情况,但 teamData 在加载后也会设置为 null。

const router = useRouter();
    const { id } = router.query;

    const [teamData, setTeamData] = useState(null);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        GetTeamData(id).then((value) => {
            setTeamData(value);
            setLoading(false);
            console.log("Got Value")
        })
    }, [id])

状态仅在代码的其余部分中引用,但在此代码段之后从未实际再次设置。我如何让 React/Next 停止将 teamData 重置为 null,作为奖励,我如何让它只调用 useEffect 一次?

P粉908643611P粉908643611374 天前469

全部回复(2)我来回复

  • P粉032649413

    P粉0326494132023-09-12 10:31:56

    useEffect 将 id 作为依赖项,因此我猜测 id 的值会更改多次,从而导致该组件重新渲染。不过,我建议您分享更多信息,因为此代码片段没有显示很多内容。

    为什么不使用服务器端道具?请参阅下面的示例。

    import type { InferGetServerSidePropsType, GetServerSideProps } from 'next'
     
    type Repo = {
      name: string
      stargazers_count: number
    }
     
    export const getServerSideProps: GetServerSideProps<{
      repo: Repo
    }> = async () => {
      const res = await fetch('https://api.github.com/repos/vercel/next.js')
      const repo = await res.json()
      return { props: { repo } }
    }
     
    export default function Page({
      repo,
    }: InferGetServerSidePropsType<typeof getServerSideProps>) {
      return repo.stargazers_count
    }

    回复
    0
  • P粉773659687

    P粉7736596872023-09-12 00:03:33

    您的效果多次触发有两个原因。

    1. Next.js 页面路由器查询参数在初始渲染期间未定义 - https://nextjs.org/docs/pages/api-reference/functions/use-router#router-object

    2. 使用严格模式时,React 18 在开发模式下卸载并重新安装组件 - https://react.dev/blog/2022/03/08/react-18-upgrade-guide#updates-to-strict-mode< /p>

    请查看按如下方式重写您的效果是否可以解决您的问题。

    useEffect(() => {
      let shouldCancel = false;
    
      if (id !== undefined) {
        GetTeamData(id).then((value) => {
          if (!shouldCancel) {
            setTeamData(value);
            setLoading(false);
            console.log("Got Value");
          }
        });
      }
    
      return () => {
        shouldCancel = true;
      };
    }, [id]);
    

    回复
    0
  • 取消回复