路由/重定向不在 React Router 4 和 Redux 授权中呈现
Posted
技术标签:
【中文标题】路由/重定向不在 React Router 4 和 Redux 授权中呈现【英文标题】:Routes/Redirects do not render in a React Router 4 & Redux Authorization 【发布时间】:2017-09-15 08:05:04 【问题描述】:我正在尝试使用 React Router 4 + Redux 实现一个简单的授权流程。
我想要的行为
如果authorization
(商店中的布尔值)是false
,任何路由都应该重定向到登录页面。
如果authorization
是true
,则任何路由都应该呈现该路由。
但是,如果在用户登录时请求登录路由,则应将其重定向到应用的根路由。
我的实现
我创建了一个组件<CheckAuth>
,并将其放置在容器中(即react-redux connect),用于访问商店中的authorization
布尔值。
<CheckAuth>
接受两个组件,<Protected>
和 <LoginPage>
,并根据布尔值在其中一个或另一个之间做出决定。
在<CheckAuth>
内部,根据authorization
呈现<Route>
到请求的组件或<Redirect>
。
<LoginPage>
中的表单将调度 LOGIN
操作,将 authorization
布尔值设置为 true。
<Protected>
中的表单将调度 LOGOUT
操作,将 authorization
布尔值设置为 false。 (此表单应与 <Protected>
分开,但我将它们放在一起以保持示例简单。)
问题
我遇到的问题是商店更改时组件似乎没有更新。硬刷新页面会更新视图,但它也会清除商店,而且只是有问题。
我可能在某处做了一些错误的假设。如果有人可以提供帮助,我将不胜感激!
代码
我创建了我的代码的简化版本,如下所示,它可以粘贴到create-react-app
App.js
文件中。下面是一个package.json
文件,用于启动并运行它。 (在我正在开发的版本中,身份验证被保存到 cookie 中,因此刷新不会清除身份验证。)
除了可能提供的任何解决方案之外,我还希望有任何关于调试 React 应用程序的技巧,尤其是路由器。
App.js:
// import Libs
import React, Component from "react"
import BrowserRouter as Router, Route, Redirect from "react-router-dom"
import createStore, applyMiddleware from "redux"
import Provider, connect from "react-redux"
import createLogger from "redux-logger"
const loggerMiddleware = createLogger()
// create Store/Reducer
const store = createStore((state = authenticated: false , action) =>
switch (action.type)
case "LOGIN":
return
authenticated: true
case "LOGOUT":
return
authenticated: false
default:
return state
, applyMiddleware(loggerMiddleware))
// <CheckAuth> component
const CheckAuth = ( authenticated, location, LoginPage, Protected ) =>
const pathname = location
if (authenticated)
if (pathname === "/login")
return <Redirect to="/" />
return <Route path=pathname component=Protected />
if (pathname === "/login")
return <Route path="/login" component=LoginPage />
return <Redirect to="login" />
const mapStateToProps = state => (
authenticated: state.authenticated
)
const CheckAuthContainer = connect(mapStateToProps)(CheckAuth)
// Log in and out Actions
const authenticate = () => (
type: "LOGIN"
)
const removeAuth = () => (
type: "LOGOUT"
)
// <Login> component
const Login = ( dispatch ) =>
const login = e =>
e.preventDefault()
dispatch(authenticate())
return (
<form onSubmit=login>
<button type="Submit">Login</button>
</form>
)
// <LoginPage> component
const LoginContainer = connect()(Login)
const ProtectedPage = ( dispatch ) =>
const logout = e =>
e.preventDefault()
dispatch(removeAuth())
return (
<div>
<h1>Protected</h1>
<form onSubmit=logout>
<button type="Submit">Logout</button>
</form>
</div>
)
const ProtectedPageContainer = connect()(ProtectedPage)
class App extends Component
render()
return (
<Provider store=store>
<Router>
<CheckAuthContainer
LoginPage=LoginContainer
Protected=ProtectedPageContainer
location=location
/>
</Router>
</Provider>
)
export default App
package.json:
"name": "test-redux-router-redirect",
"version": "0.1.0",
"private": true,
"dependencies":
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-redux": "^5.0.4",
"react-router-dom": "^4.1.1",
"redux": "^3.6.0",
"redux-logger": "^3.0.1",
"redux-thunk": "^2.2.0"
,
"devDependencies":
"react-scripts": "0.9.5"
,
"scripts":
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
【问题讨论】:
【参考方案1】:我想通了。
The React Router documentation's section on Redux integration 实际上直接解决了这个案例,但不知怎么我误解了如何应用它。
将<CheckAuthContainer>
组件传递给withRouter
解决了我的问题。所以第 45 行看起来像这样:
const CheckAuthContainer = withRouter(connect(mapStateToProps)(CheckAuth))
我还没有在我正在开发的真实应用中尝试过这个。希望它也能在那里工作!
【讨论】:
以上是关于路由/重定向不在 React Router 4 和 Redux 授权中呈现的主要内容,如果未能解决你的问题,请参考以下文章
React Hooks with React Router v4 - 我如何重定向到另一个路由?
React Router v4 - 使用不同的查询参数重定向到相同的路由
react-router-dom之Redirect(重定向)理解