首页 > 解决方案 > 在 React 中重定向到具有不同页面布局的页面

问题描述

成功登录后,我无法重定向到具有不同 CSS 布局的页面。例如,我有一个带有典型导航栏的公司页面,如主页、关于我们、服务和登录。成功登录后,它会重定向到类似 Admin Bootstrap Dashboard 页面。但我不断获得公司页面导航栏,但 url 清楚地显示 localhost:3000/dashboard。我哪里做错了?谢谢,代码如下:

App.js

 <Switch>
      <Fragment>   
      <Helmet>
        <title>Demo</title>
        <meta content="width=device-width, initial-scale=1.0" name="viewport"/>
        <meta content="" name="keywords"/>
        <meta content="" name="description"/>  
      </Helmet>   
          <Header/> 
          <Route exact path="/" component={Home}/>
          <Route exact path="/login" component={Login}/>
          <Route exact path="/services" component={Services}/>   
      </Fragment>
 </Switch>

In the Login.js

  render() {
        if(this.state.isAuthenticated){
            return(<Redirect to={'/Dashboard'}/>)
        }


In the Dashboard.js


    render() {
        return (
            <div>
                <h1>Hello</h1>
            </div>
        )
    }
}

标签: reactjs

解决方案


将 isUserAuthenticated 之类的状态变量存储在受保护的 Route 中是一个坏主意,在您的情况下,它就是仪表板。让我解释一下上面的代码是做什么的,它首先呈现仪表板组件,然后在第一次安装仪表板之后,代码决定用户是否经过身份验证并有条件地重定向。还要提到变量 unauthenticated 是组件级别的状态,这意味着其他组件无法知道用户是否经过身份验证。

现在它可能会出错,您可能需要标题组件中用户的身份验证状态,如果用户通过身份验证或登录按钮,您将在其中呈现注销按钮。其他一些组件可能还需要用户的身份验证状态。

因此,最好的方法是使用更好的状态管理,如上下文 API 或 redux,如果您对它感到满意的话。

是否使用 redux 完全是另一回事。所以这里有一个使用上下文 API 来解决问题的简单解决方案。

在 AuthContext.js 中

const AuthContext = React.CreateContext(null)


const AuthContextProvider = (props) => {
    const [isAuthenticated, setIsAuthenticated] = useState(false)

    const login = () => {
        // your authentication logic
        setIsAuthenticated(true)
    }

    const logout = () => {
        // your logout logic
        setIsAuthenticated(false)
    }

    return (
        <AuthContext.Provider value={{isAuthenticated, login, logout}}>
           {props.children}
        <AuthContext.Provider>
    )
}

export default AuthContextProvider;

在 App.js 中使用 AuthContextProvider 包装您的应用

function App(props) {
    return (
        <AuthContextProvider>
            // all other app logic
            // like <Switch>
            //          <Route exact path="/" component={Home}/>
            //      <Switch/>
        <AuthContextProvider>
    )
}

现在要使仪表板路由受到保护,您可以采用这种方法制作一个新的私有路由组件

在 PrivateRoute.js

 function PrivateRoute(props) {
    // keep in mind path is required as a prop
    const { path, children, ...rest } = props;

    // using the AuthContext to get the state variable isAuthenticated
    const { isAuthenticated } = useContext(AuthContext);


    return (
        <Route
        exact
        path={path}
        render={({ location }) =>
            isAuthenticated ? (
            children
            ) : (
            <Redirect to={{ pathname: '/login', state: { from: location } }} />
            )
        }
        />
    );
}

在您的情况下呈现受保护的页面(如仪表板)时,在 Switch 内呈现这样的路由,任何其他私有路由也是如此

<Switch>
    // other routes
    // for example <Route exact path="/" component={Home}/>

    // The Dashboard route
    <PrivateRoute path="/dashboard">
        <Dashboard/>
    <PrivateRoute/>

<Switch/>

请记住,登录和注销功能来自上下文,因此任何使用登录或注销功能的组件也需要使用 AuthContext。如果您的应用程序已经在使用它,或者您对 redux 更满意,您也可以使用 redux 实现相同的逻辑。

这在代码中实现起来要困难得多,所以让我知道您是否可以在您的应用程序中实现它。

如果您需要参考,这里有一些文档链接。

https://reactjs.org/docs/context.html

https://reacttraining.com/react-router/web/example/auth-workflow


推荐阅读