繁体   English   中英

为什么在使用 React Router V6 保护路由时,我使用 AWS Amplify 的 React Authentication 组件会被无限渲染

[英]Why is my React Authentication component using AWS Amplify being rendered infinitely when using React Router V6 to protect routes

我正在尝试使用 React、AWS Amplify 和 React Router V6 创建我自己的自定义身份验证,我的目标是保护某些路由,以便未登录的用户无法访问它们。

我的代码在这里:

import './App.css';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import Navbar from './components/Navbar/Navbar';
import Dashboard from './components/Dashboard/Dashboard';
import Reports from './components/Reports/Reports';
import Patients from './components/Patients/Patients';
import { BrowserRouter, Navigate, Outlet, Route, Routes, useLocation, } from 'react-router-dom';
import React, { useEffect, useState } from 'react';
import '@aws-amplify/ui-react/styles.css';
import Signup from './components/Signup/Signup';
import Signin from './components/Signin/Signin';
import { Auth } from 'aws-amplify';

const darkTheme = createTheme({
  palette: {
    mode: 'dark',
  }
});

const useAuth = () => {
  const [user, setUser] = useState(null);

  useEffect(() => {
    const fetchUser = async () => {
      const response = await Auth.currentAuthenticatedUser();
      setUser(response);
    }
    fetchUser();
  })

  return { user };
}

function RequireAuth() {
  const auth = useAuth();
  const location = useLocation();
  console.log(auth);

  return (
    auth
      ? <Outlet/>
      : <Navigate to='/signin' state={{ from: location}} replace/>
  );
}

const App = () => {

  return (
    <ThemeProvider theme={darkTheme}>
      <BrowserRouter>
        <Routes>
          <Route element={<RequireAuth />}>
            <Route path="/" element={<Navbar />}>
              <Route path="dashboard" element={<Dashboard />} />
              <Route path="patients" element={<Patients />} />
              <Route path="reports" element={<Reports />} />
            </Route>
          </Route>
          <Route path="/signin" element={<Signin />} />
          <Route path="/signup" element={<Signup />} />
        </Routes>
      </BrowserRouter>
    </ThemeProvider>
  );
}

export default App;

我花了一整天的时间尝试了无数种方法,但我一直得到相同的结果。 我想做的是保护 3 条路线仪表板、患者和报告。 每当我单击登录按钮时,我都会得到当前用户的大约 500 条日志,如下所示:

在此处输入图像描述

有谁知道是什么触发了这个组件无限地重新渲染(因此执行了我的 console.log(user) 函数),有什么解决方案可以解决这个问题吗?

useEffect挂钩似乎缺少依赖项数组,因此每个渲染周期都会触发其回调。 由于效果更新 state,它会触发重新渲染。

添加一个依赖数组。

useEffect(() => {
  const fetchUser = async () => {
    const response = await Auth.currentAuthenticatedUser();
    setUser(response);
  }
  fetchUser();
}, []);

如果您需要在安装路由时多次运行此效果,那么您可能需要添加依赖项,例如location if/when 路由路径更改。

例子:

const { pathname } = useLocation();

useEffect(() => {
  const fetchUser = async () => {
    const response = await Auth.currentAuthenticatedUser();
    setUser(response);
  }
  fetchUser();
}, [pathname]);

由于useEffect挂钩在初始渲染周期结束时运行,您可能还希望有条件地等待渲染插座或重定向,直到user state 被填充。

例子:

const useAuth = () => {
  const [user, setUser] = useState(); // <-- initially undefined

  useEffect(() => {
    const fetchUser = async () => {
      const response = await Auth.currentAuthenticatedUser();
      setUser(response);
    }
    fetchUser();
  }, []);

  return { user };
}

...

function RequireAuth() {
  const auth = useAuth();
  const location = useLocation();

  if (auth === undefined) {
    return null; // or loading indicator, etc...
  }

  return (
    auth
      ? <Outlet/>
      : <Navigate to='/signin' state={{ from: location }} replace/>
  );
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM