#javascript #reactjs
Вопрос:
Я создаю веб — страницу с несколькими частными маршрутами. Если пользователь не вошел в систему, я хочу перенаправить его на домашнюю страницу. Если пользователь вошел в систему, я хочу отобразить страницу, к которой он изначально пытался получить доступ. Настройка, которую я в настоящее время использую, работает для этой цели, но всякий раз, когда пользователь входит в личный маршрут, а затем обновляет страницу, личный маршрут перенаправляет его на домашнюю страницу. К сожалению, мой loggedInProvider запускает код входа в систему ПОСЛЕ того, как частный маршрут проверяет логическое значение LoggedIn и перенаправляет их. ТАКИМ образом, технически при обновлении недостаточно быстро регистрируется человек. Есть ли способ дождаться запуска эффекта использования, вошедшего в систему, прежде чем запускать код частного маршрута?
Вот код useEffect в моем loggedInContext:
import { useHistory } from "react-router-dom";
import React, { createContext, useState, useEffect } from "react";
import Cookie from "js-cookie";
import axios from "axios";
export const LoggedInContext = createContext();
export function LoggedInProvider(props) {
const history = useHistory();
const [loggedIn, setLoggedIn] = useState(false);
const [token, setToken] = useState("");
const [loading, setLoading] = useState();
const [userData, setUserData] = useState({});
//use loading variable to make splash screen - just export and write an if statement to show splashscreen if loading is true in top level app
const signUserIn = (token, userData, path = undefined) => {
Cookie.set("token", token);
changeLogIn(true);
setUserData(userData.user);
NavigateAway(path);
};
useEffect(() => {
console.log("UseEffect from LoggedIn");
setLoading(true);
const jwt = Cookie.get("token");
const fetchData = async () => {
try {
const config = {
method: "POST",
url: "https://prothesist-backend.herokuapp.com/api/v1/user/sign-in/token",
headers: {
"Content-Type": "application/json",
},
data: {
token: jwt,
},
};
const { data } = await axios(config);
setLoggedIn(true);
// setUserData(data.user);
signUserIn(jwt, data);
setLoading(false);
//use userdata to fill in data
} catch (err) {
console.log(err);
}
};
if (jwt) {
fetchData();
} else {
setLoggedIn(false);
setLoading(false);
}
}, []);
const updateUserData = (data) => {
setUserData(data);
};
const changeLogIn = (val) => {
setLoggedIn(val);
if (!val) NavigateAway("/");
};
const handleSignOut = () => {
console.log("signedout");
var myHeaders = new Headers();
myHeaders.append("Cookie", "jwt=loggedout");
var requestOptions = {
method: "GET",
headers: myHeaders,
redirect: "follow",
};
fetch(
"https://prothesist-backend.herokuapp.com/api/v1/user/logout",
requestOptions
)
.then((response) => response.text())
.then((result) => {
setLoggedIn(false);
Cookie.set("token", "");
console.log(result);
})
.catch((error) => console.log("error", error));
};
const setTokens = (data) => {
localStorage.setItem("token", JSON.stringify(data));
setToken(data);
};
const NavigateAway = (path) => {
history.push(path);
};
return (
<LoggedInContext.Provider
value={{
userData,
setUserData: setUserData,
loading,
loggedIn,
changeLogIn,
handleSignOut,
token,
setToken: setTokens,
}}
>
{props.children}
</LoggedInContext.Provider>
);
}
Вот мой личный маршрут:
import React, { useContext, useEffect } from "react";
import { Redirect, Route } from "react-router-dom";
import { LoggedInContext } from "contexts/LoggedIn.js";
export default function PrivateRoute({ children, ...rest }) {
const { loggedIn } = useContext(LoggedInContext);
return (
<Route
{...rest}
render={({ location }) =>
loggedIn ? (
children
) : (
<Redirect to={{ pathname: "/", state: { registerModal: true } }} />
)
}
/>
);
}
Ответ №1:
Я бы подумал, что вы просто добавите loading
чек:
export default function PrivateRoute({ children, ...rest }) {
const { loggedIn, loading } = useContext(LoggedInContext);
return (
<Route
{...rest}
render={({ location }) => {
if (loggedIn) return children;
else if (loading) return <Spinner />;
else return (
<Redirect to={{ pathname: "/", state: { registerModal: true } }} />
);
}}
/>
);
}
а затем, возможно, по умолчанию loading
в вашем провайдере будет установлено значение true
Комментарии:
1. Хм, похоже, у него та же проблема с этим методом.