为什么每次路由时都会触发nextjs的useEffect



我在Layout组件中有一个useEffect函数,它获取我的userData并将其存储在redux-store中,但它会随着每次路由更改而触发.

我希望useFffect函数第一次运行,并且在我改变路由时不再触发。这与向服务器发送更多无用的请求是不正确的。我该怎么做呢?

这是我的Layout组件:
import { useEffect, useState } from "react";
import Navbar from "../navbar/navbar";
import Footer from "../footer/footer";
import Head from "next/head";
import { useCookies } from "react-cookie";
import { useDispatch, useSelector } from "react-redux";
import axios from "axios";
import { getUserData } from "../../redux/actions/Auth";
const Layout = ({ children }) => {
const [cookie, setCookie] = useCookies(["token"]);
const dispatch = useDispatch();
useEffect(() => { // this useEffect triggers every time i route !! 
const { token } = cookie;
if (token) {
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
dispatch({ type: "IS_LOGGED_IN" });
dispatch(getUserData(token));
}
}, []);
return (
<div className="layout" dir="rtl">
<Head>
<meta name="description" content="" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
rel="preconnect"
href="https://fonts.gstatic.com"
crossOrigin="true"
/>
<link
href="https://fonts.googleapis.com/css2?family=Noto+Kufi+Arabic:wght@100;200;300;400;500;600;700;800;900&display=swap"
rel="stylesheet"
/>
<link
rel="stylesheet"
type="text/css"
charset="UTF-8"
href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css"
/>
<link
rel="stylesheet"
type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css"
/>
</Head>
<Navbar />
{children}
<Footer />
</div>
);
};
export default Layout;

问题:

你正在使用useEffect钩子,它在组件挂载时触发,也会在每次路由更改时触发,这是默认的,正确的useEffect钩子的行为,因为你在Layout组件上使用它,它会在每次路由更改时重新渲染。

解决方案:

有一些解决方案可以处理这些情况,比如在Layer组件的父组件上实现getUserData(token),这样就不会在每次路由更改时重新渲染。

另一个解决方案是使用另一个状态变量来保存API调用状态。你有一个IS_LOGGED_IN动作,可能会改变你的减速机,像这样:

case IS_LOGGED_IN:
return {
...state,
isUserLoggedIn: true
}
因此,在调度getUserData之前,您需要在useEffect上获取并检查这个示例属性:
const isLoggedIn = useSelector(state => state.user.isUserLoggedIn) // get isUserLoggedIn from the state
useEffect(() => { 
if (!isLoggedIn) {  // -----> getUserData if user is not logged in
const {token} = cookie;     
if (token) {
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
dispatch({ type: "IS_LOGGED_IN" });
dispatch(getUserData(token));
}
}
}, [isLoggedIn]);

解释:

一旦使用Layout组件,isLoggedIn值为false(因为用户没有登录),因此dispatch(getUserData(token))方法将调用并获取数据。在此之后,isLoggedIn将变为true,因此useEffect中的条件语句将检查它,并且不再允许再次调度getUserData

注意:您可能需要在reducer上使用适当的过程进行另一个操作,以在用户登录或注销应用程序之间进行切换。

相关内容

  • 没有找到相关文章

最新更新