我使用的是react-router-dom v5.2。
登录后,我希望我的页面重定向到/home来自/。登录表在/。
当我尝试在没有任何异步功能的情况下执行身份验证时(即,将用户名和密码与react中的硬编码值进行比较),一切工作正常。
但是,当我使用express和mongo执行身份验证时,登录时的重定向停止工作。如果我再次登录,就会发生重定向。受保护的路由仍然有效(如果用户未登录,则重定向到登录页面)。
这是一个关于这个问题的小演示,其中我使用了do auth with express + mongo ie。异步复制。这并不像预期的那样工作。
这是应用程序的链接,在这里我使用硬编码的用户名和密码(都是"test")来执行身份验证。这里没有异步。这可以达到预期的效果。用户名和密码都是"test“。https://poke-zoo.herokuapp.com/
下面是App.js:
const ProtectedRoute = ({ component: Component, ...rest }) => {
const authState = useSelector(selectorAuth)
// const location = useLocation()
return (
{
if (authState.isUserLoggedIn) {
return
} else {
return (
)
}
}}
/>
)
}
const App = () => {
return (
"404 Not found."} />
)
}下面是ModalLogin.js。
const ModalLogin = props => {
const { loginModalBool, setLoginModalBool } = props
const [username, setUsername] = useState("")
const [password, setPassword] = useState("")
const dispatch = useDispatch()
const history = useHistory()
const attemptLogin = e => {
e.preventDefault()
dispatch(tryLogin(username, password))
history.push("/home")
}
return (
Login
setLoginModalBool(!loginModalBool)}>
close
setUsername(e.target.value)}
placeholder="username"
/>
setPassword(e.target.value)}
type="password"
placeholder="password"
/>
log in
)
}下面是authSlice.js。
import { createSlice } from "@reduxjs/toolkit"
import axios from "axios"
const initialState = {
isUserLoggedIn: false,
username: "",
}
export const authSlice = createSlice({
name: "auth",
initialState: initialState,
reducers: {
login: (state, action) => {
const user = action.payload
if (!user) return alert("Login failed. Incorrect username or password.")
state.username = user.username
state.isUserLoggedIn = true
},
logout: (state, action) => {
// window.localStorage.removeItem("loggedInUser")
state.username = ""
state.isUserLoggedIn = false
},
signup: (state, action) => {
const user = action.payload
state.username = user.data.username
state.isUserLoggedIn = true
},
},
})
export const tryLogin = (username, password) => {
return async dispatch => {
try {
const response = await axios.post("/api/auth/login", {
username: username,
password: password,
})
const user = {
token: response.headers["auth-token"],
username: response.data.username,
}
// window.localStorage.setItem("token", response.headers["auth-token"])
dispatch(login(user))
} catch (e) {
alert("Incorrect Username/Password.")
}
}
}
export const selectorAuth = state => state.auth
export const { login, logout } = authSlice.actions
export default authSlice.reducer我使用redux-toolkit的react-router有误吗?
下面是Github存储库
发布于 2020-06-06 15:22:03
您的代码没有定义登录后的重定向逻辑。你可以用两种方法来做这件事。
第一:如果你想让你的路由在认证的情况下重定向,你可以为认证定义另一个重定向包装器。
const AuthRoute = ({ component: Component, ...rest }) => {
const authState = useSelector(selectorAuth)
const location = useLocation()
return (
{
if (!authState.isUserLoggedIn) {
return
} else {
return (
)
}
}}
/>
)
}
const App = () => {
return (
// It is for login users to redirect to home page
"404 Not found."} />
)
}第二:另一种方法可以使用history.push()或history.replace()进行强制处理:
const Layout = () => {
const authState = useSelector(selectorAuth);
const history = useHistory();
useEffect(() => {
// if isUserLoggedIn turned to true redirect to /home
if (authState.isUserLoggedIn) {
history.push("/home");
}
}, [authState.isUserLoggedIn]); // triggers when isUserLoggedIn changes
return (
"404 Not found."} />
);
};
const App = () => {
return (
);
};为什么你的代码不能工作?看看下面的代码:
"404 Not found."} />它能做什么?它会检查您的浏览器路径,并从上到下检查它是否与给定的路由规则匹配。如果Route path匹配,则它呈现组件,如果不匹配,则继续向下访问每个Route,直到它与您的404匹配。
因此,回到您的情况;当您登录时,您没有离开"/“路径。因为没有实现离开"/“路径的逻辑。因此,即使它已通过身份验证,它也会再次与登录页面匹配。它与路由路径(登录页面)匹配并停留在那里。它不会继续并在ProtectedRoute上尝试您的逻辑。
发布于 2021-02-25 04:52:08
当前接受的答案修复了您的问题,但没有正确确定您遇到问题的原因。所以我想为你(以及其他阅读这篇文章的人)解释一下。
问题:重定向太快
const attemptLogin = e => {
e.preventDefault()
dispatch(tryLogin(username, password))
history.push("/home")
}此代码将调度tryLogin和立即呼叫history.push("/home")。它不等待调度的操作完成并更新存储。
当你调用history.push("/home")您的应用程序加载ProtectedRoute对于组件Home。在ProtectedRoute使用选择器检查authState.isUserLoggedIn。如果是false,然后重定向到"/"。
因此,如果您重定向到"/home"的值之前authState.isUserLoggedIn已更新,则您最终将被重定向回"/"而不是能够查看Home组件。
这就是为什么异步身份验证会有这些问题的原因:
当我尝试在没有任何异步功能的情况下执行身份验证时(即,将用户名和密码与react中的硬编码值进行比较),一切工作正常。
但是,当我使用express和mongo执行身份验证时,登录时的重定向停止工作。
解决方案:重定向前等待
您需要等待authState更新之前重定向到受保护的路由。
有很多方法可以做到这一点,但一般来说,我们希望使用选择器来侦听发布到redux状态的更改。这里有一种方法,它使用ModalLogin有条件地呈现Redirect组件。我还建议为登录错误包括某种类型的选择器,以防分派完成解决但登录不成功。您可能希望在模式中向用户显示一条错误消息。
const ModalLogin = props => {
const { loginModalBool, setLoginModalBool } = props
const [username, setUsername] = useState("")
const [password, setPassword] = useState("")
const dispatch = useDispatch()
const history = useHistory()
// Look at the authState from redux. This value will automatically update.
const authState = useSelector(selectorAuth)
const attemptLogin = e => {
e.preventDefault()
dispatch(tryLogin(username, password))
// don't redirect here anymore
}
// Once logged in, render the redirection
if ( authState.isUserLoggedIn ) {
return (
);
}
// Otherwise, render the modal
return (
/* your current code */
)
}发布于 2020-06-05 03:27:35
老实说,我所做的是在用户登录时使用普通的老式javascript来更改位置。
window.location = "/redirect"https://stackoverflow.com/questions/62154408
复制相似问题