ReactJs:PrivateRoute 组件被调用两次
Posted
技术标签:
【中文标题】ReactJs:PrivateRoute 组件被调用两次【英文标题】:ReactJs: PrivateRoute component gets called twice 【发布时间】:2021-09-16 06:24:36 【问题描述】:我有这个用于管理身份验证的 privateRoute 组件:
const PrivateRoute = ( component: Component, auth, ...rest ) =>
// This gets logged twice when I navigate in the app
// Using history.push("/url")
// And gets logged once when I type the url and hit enter on the browser
console.log(
"===============INSIDE PrivateRoute Component========================"
);
return (
<Route
...rest
render=(props) =>
auth.isAuthenticated === true ? (
<Component ...props />
) : (
<Redirect to="/login" />
)
/>
);
;
奇怪的是,当我在应用程序中导航时,该组件被记录了两次。例如,当我点击触发此代码的按钮时:
this.props.history.push("/edit-page-after-login");
我在 App.js 中有这个:
<PrivateRoute
path="/edit-page-after-login"
component=EditProfileAfterLogin
/>
我有一个在该路由中呈现的组件:
export default class EditProfileInSettings extends Component
componentDidMount()
console.log(
"???? ~ file: EditProfileInSettings.js ~ line 5 ~ EditProfileInSettings ~ componentDidMount ~ componentDidMount"
);
render()
return <div>Test</div>;
因此,当我使用 history.push
导航到该组件时,会记录下来:
===============INSIDE PrivateRoute 组件========================= ??? ~ 文件:EditProfileInSettings.js ~ 第 5 行 ~ EditProfileInSettings ~ componentDidMount ~ componentDidMount ===============INSIDE PrivateRoute 组件========================
由于某些奇怪的原因,PrivateRoute 组件被称为 TWICE,这导致我尝试实现的逻辑出现一些问题。
但是,当我在浏览器中写入 url 并输入时,它的行为是正确的,它只会被称为 ONCE:
===============INSIDE PrivateRoute 组件========================= ??? ~ 文件:EditProfileInSettings.js ~ 第 5 行 ~ EditProfileInSettings ~ componentDidMount ~ componentDidMount
知道这里发生了什么吗?
编辑 1: 我注意到这个错误只发生在我对组件内的后端进行 API 调用时:
class PrivateRouteTestComponent extends Component
componentDidMount()
console.log("PrivateRouteTestComponent.componentDidMount is called!");
// If I comment this out, the problem will not occur.
// It only occurs with this line
// It does an API call to the backend to get user profile
this.props.getAuthenticatedUserProfile();
render()
return (
<div>
<button
onClick=() =>
this.props.history.push("/videos-page");
>
Home
</button>
<h6>Private route test component</h6>
</div>
);
编辑2:我终于找到了为什么会出现这个错误。调用一个向商店分派东西的函数将更新PrivateRoute
,因此它将再次被调用:
class PrivateRouteTestComponent extends Component
componentDidMount()
console.log("PrivateRouteTestComponent.componentDidMount is called!");
// This doesn't cause the problem
testBackendCall();
// This causes the problem
// Because it dispatches an action to the store
// So PrivateRoute gets updated
this.props.testBackendCallThatDispatchesSomethingToTheStore();
render()
return (
<div>
<button
onClick=() =>
this.props.history.push("/videos-page");
>
Home
</button>
<h6>Private route test component</h6>
</div>
);
【问题讨论】:
reactrouter.com/web/api/Routeexact
部分呢??
我知道。但我看不出它与我提到的任何事情有什么关系。
【参考方案1】:
您正在混合功能组件和基于 React 类的组件,并希望 PrivateRoute
中的日志记录和 EditProfileInSettings
中的日志记录在渲染周期的同一时刻完成 - 但事实并非如此。
在EditProfileInSettings
中,您登录安装阶段 (componentDidMount
),这在组件的渲染中发生一次(如果未卸载)。
在PrivateRoute
中,您登录渲染阶段(认为相当于render
上的类Component
),每次React 需要更新您的组件时都会发生这种情况,因为它的道具正在改变。
如果您希望两个日志记录相同,请将您的日志记录放在PrivateRoute
上的useEffect()
,或者将您的日志记录放在EditProfileInSettings
上的render()
。
然后,要知道为什么你的功能组件被渲染两次,记录你所有的 props 并找出两个循环之间的差异。
【讨论】:
【参考方案2】:这就是解决我的问题的方法。仅在挂载时使用 React 钩子在功能组件中执行代码。
const PrivateRoute = ( component: Component, auth, ...rest ) =>
React.useEffect(() =>
// EXECUTE THE CODE ONLY ONCE WHEN COMPONENT IS MOUNTED
, []);
return (
<Route
...rest
render=(props) =>
auth.isAuthenticated === true ? (
<Component ...props />
) : (
<Redirect to="/login" />
)
/>
);
;
【讨论】:
以上是关于ReactJs:PrivateRoute 组件被调用两次的主要内容,如果未能解决你的问题,请参考以下文章
将自定义数据传递给 React 中的 PrivateRoute 组件
PrivateRoute 在 reactjs react-router-dom 中不起作用
错误:[PrivateRoute] 不是 <Route> 组件。 <Routes> 的所有子组件必须是 <Route> 或 <React.Fragment&g