路由/重定向不在 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,任何路由都应该重定向到登录页面。 如果authorizationtrue,则任何路由都应该呈现该路由。 但是,如果在用户登录时请求登录路由,则应将其重定向到应用的根路由。

我的实现

我创建了一个组件<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 实际上直接解决了这个案例,但不知怎么我误解了如何应用它。

&lt;CheckAuthContainer&gt; 组件传递给withRouter 解决了我的问题。所以第 45 行看起来像这样:

const CheckAuthContainer = withRouter(connect(mapStateToProps)(CheckAuth))

我还没有在我正在开发的真实应用中尝试过这个。希望它也能在那里工作!

【讨论】:

以上是关于路由/重定向不在 React Router 4 和 Redux 授权中呈现的主要内容,如果未能解决你的问题,请参考以下文章

React Hooks with React Router v4 - 我如何重定向到另一个路由?

React Router v4 - 使用不同的查询参数重定向到相同的路由

React Router 在一个重定向中包装多个路由

react-router-dom之Redirect(重定向)理解

react嵌套路由(多重路由)重定向,重定向到404页面,路由重定向

如何使用 react-router 重定向到另一条路由?