javascript React/Next更新状态并在使用后重置它

qxgroojn  于 2023-06-28  发布在  Java
关注(0)|答案(3)|浏览(115)

我试图从一个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])

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

2fjabf4q

2fjabf4q1#

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

  1. Next.js页面路由器查询参数在初始渲染期间未定义-https://nextjs.org/docs/pages/api-reference/functions/use-router#router-object
  2. React 18在使用严格模式时在dev模式下卸载和重新挂载组件-https://react.dev/blog/2022/03/08/react-18-upgrade-guide#updates-to-strict-mode
    请查看如下重写效果是否可以解决您的问题。
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]);
qzwqbdag

qzwqbdag2#

useEffect有id作为依赖项,所以我猜id的值不止一次改变,这会导致这个组件重新呈现。尽管如此,我还是建议你分享更多的信息,因为这个代码片段并没有显示很多东西。
为什么不用服务器端的 prop 呢?请参见下面的示例。

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
}
k4emjkb1

k4emjkb13#

当你在API调用中使用useEffect时,你通常需要处理一些依赖值为null和组件被卸载的情况:

useEffect(()=>{

    if(!id) return; // do nothing if no id. 
    let wasUnmounted = false;

    fetch(...).then(resp=>resp.json()). // handle http success etc
        .then(data=>{
           if(!wasUnmounted) {
               setState(data);
               setTimeout(()=>setLoading(false), 0); // since setState would cause an unadorned setLoading to be ignored
           }
           return null;
        });

     return ()=>{
        wasUnmounted = true;
     };
}, [id]);

相关问题