#javascript #reactjs #state
Вопрос:
Я столкнулся с проблемой с защищенными маршрутами и аутентификацией защищенных маршрутов.
Я использую AuthContext для полной аутентификации пользователя в веб-приложении. Я сохраняю все пользовательские данные внутри состояния. С помощью useEffect и sessionStorage я сохраняю объект пользователя, чтобы он мог использоваться после перезагрузки страницы.
[...]
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState({})
useEffect(() => {
const sessionUser = sessionStorage.getItem("user")
if(!sessionUser) return
changeUser(JSON.parse(sessionUser))
}, [])
const hasRank = (ranks) => {
if(!Object.keys(user).length > 0) return false
const matchingPerms = ranks.filter(rank => user.rank.includes(rank))
return matchingPerms.length > 0
}
const changeUser = (data) => {
setUser(data)
if(Object.keys(data).length > 0) {
return sessionStorage.setItem("user", JSON.stringify(data))
}
return sessionStorage.removeItem("user")
}
}
[...]
Для защиты определенных страниц я использую компонент Защищенного маршрута, который проверяет, вошел ли пользователь в систему или нет.
[...]
const auth = useContext(AuthContext)
const isAuthorized = auth.hasRank(rest.rank)
<Route
{...rest}
render={props => {
return isAuthorized ? (
<Component {...props} />
) : (
<Redirect to="/auth/login" />
)
}}
/>
Сохранение и извлечение в хранилище сеансов и из него работают нормально до тех пор, пока я не захочу отображать содержимое, находящееся внутри защищенного маршрута — я всегда перенаправляюсь на страницу входа в систему, потому что объект пользователя пуст из-за перезагрузки, а состояние не обновляется достаточно рано. Поэтому защищенный маршрут проверяет аутентификацию с помощью пустого объекта, что приводит к перенаправлению на страницу входа в систему.
Как я могу дождаться обновления состояния пользователя, прежде чем проверять аутентификацию внутри защищенного маршрута?
Редактировать:
Компонент приложения:
return (
<Router>
<Switch>
<Route path="/auth/register" component={Register} />
<Route path="/auth/login" component={LogIn} />
<Route path="/err/404" component={Page404} />
<Route path="/" component={PanelRoutes}/>
</Switch>
</Router>
)
Компонент «Маршруты панелей»:
return (
<div className="skin-default fixed-layout">
<div id="main-wrapper">
<Topbar />
<Sidebar />
<div className="page-wrapper">
<div className="container-fluid">
<Switch>
<Route exact path="/" component={Homepage} />
<Route exact path="/legal/imprint" component={Imprint} />
<Route exact path="/legal/privacy" component={Privacy} />
<ProtectedRoute exact path="/mc/sounds" component={McSounds} rank={["ADMIN", "MC"]} />
<ProtectedRoute exact path="/admin/users" component={AdminUsers} rank={["ADMIN"]} />
</Switch>
</div>
</div>
</div>
</div>
)
с уважением
Комментарии:
1. мне нужно увидеть ваше <Приложение /> или корневой компонент. Потому что мы всегда предполагаем, что все, что вы получаете от корня, когда дело доходит до аутентификации, должно передаваться детям через контекст. Предполагается, что вы являетесь только потребителем этого чека. При обновлении вы все равно снова проходите через корневой компонент.
2. Я отредактировал свой первоначальный вопрос и добавил компонент приложения, в котором «хранятся»маршруты
3. Спасибо. могу я спросить, где
AuthProvider
он используется? Либо вашApp
, либоPanelRoutes
вам нужно его потреблять? или есть компонент верхнего корня, потребляющий это, могу ли я также увидеть этот код, спасибо ? Также для первых двух разделов кода, каковы их имена компонентов ?4. Первые два имени компонентов: AuthContext и ProtectedRoute. Сам компонент приложения или маршрутов панели не использует его, но компоненты внутри маршрутов панели используют AuthContext.