首页 > 解决方案 > 在成功登录和将信息从一个组件传递到一个组件时反应隐藏/显示菜单

问题描述

React 的新手,我的大部分学习都是通过实验完成的。

我有以下组件:

应用程序.js

import React, { Component } from 'react';

// Libraries and Utilities
import { BrowserRouter, Switch, Route } from 'react-router-dom';

// Components
import Layout from './components/layout/Layout';
import Home from './components/home/Home';
import Login from './components/login/Login';

class App extends Component {
    static displayName = App.name;

    render() {
        return (
            <BrowserRouter basename='/myapp>
                <Layout>
                    <Switch>
                        <Route path="/" exact component={Home} />
                        <Route path='/login' component={Login} />
                        <Route path='/admin' component={Admin} />
                    </Switch>
                </Layout>
            </BrowserRouter>
        );
    }
}

export default App;

布局.js

import React, { Component } from 'react';
import NavMenu from '../navigation/NavMenu';

class Layout extends Component {
  render() {
        return (
            <div className="container-fluid">
                <div className="row">
                    <NavMenu />
                </div>
                <div className="main layout">
                    {this.props.children}
                </div>
                <div className="row">
                    <Footer />
                </div>
            </div>
        );
    }
};

export default Layout;

导航菜单.js

import React, { Component } from 'react';
import { NavLink } from "react-router-dom";

import logo from '../../assets/logo.svg';

class navigation extends Component {
    constructor(props) {
        super(props)
        this.state = {
            loggedIn: false
        }
    }

    render() {
        return (
            <div className="row">
                <nav className="navbar navbar-expand navbar-dark bg-primary fixed-top">
                    <a className="navbar-brand" href="/">
                        <img src={logo} width="250" height="70" alt="" />
                    </a>

                    <div className="collapse navbar-collapse">
                        <ul className="navbar-nav mr-auto">
                            <li className="nav-item" to={'/'}>
                                <NavLink exact={true} className="navbar-brand" activeClassName='active' to='/'>Home</NavLink>
                            </li>
                            <li className="nav-item" to={'/admin1'}>
                                <NavLink exact={true} className="navbar-brand" activeClassName='active' to='/admin1'>Admin 1</NavLink>
                            </li>
                            <li className="nav-item" to={'/admin2'}>
                                <NavLink exact={true} className="navbar-brand" activeClassName='active' to='/admin1'>Admin 2</NavLink>
                            </li>
                        </ul>

                        <ul className="navbar-nav">
                            <li className="nav-item">
                                <NavLink exact={true} className="navbar-brand" activeClassName='active' to='/login'>
                                    <i className="fa fa-sign-in" aria-hidden="true"></i>
                                </NavLink>
                            </li>
                        </ul>
                    </div>
                </nav>
            </div>
        )
    };
};

export default navigation;

登录.js

import React, { Component } from 'react';

class login extends Component {
    constructor(props) {
        super(props)

        this.state = {
            loginModel: {
                UserName: '',
                Password: ''
            }
        }

        this.handleInputChange = this.handleInputChange.bind(this)
        this.handleSubmit = this.handleSubmit.bind(this)
    }

    handleInputChange(event) {
        const target = event.target
        const value = target.type === 'checkbox' ? target.checked : target.value
        const name = target.name

        this.setState(prevState => ({
            loginModel: {
                ...prevState.loginModel,
                [name]: value
            }
        }))
    }

    handleSubmit(event) {
        // At This Stage, I perform an API Call (via axios) and I get the Response Data.
        const url = 'some  url'
                axios.post(url, this.state.loginModel).then((response) => {
                    if (response.status === 200) {
                        // Get token from response to be used in authenticated api calls.
                        const responseData = response.data
                        let authToken = responseData.token
                        console.log('authToken', authToken)

                        swal({
                            title: "My Application",
                            text: "Logon Successful.",
                            icon: "success"
                        }).then((value) => {
                            // Go to the Admin Home.
                            const path = '/admin'
                            this.props.history.push(path);
                        })
                    }
                }, (err) => {
                    console.log(err.response)
                        const msg = err.response.data.message
                        const icon = err.response.data.icon
                    swal({
                        title: "My Application",
                        text: msg,
                        icon: icon
                    })
                })
        )

        event.preventDefault();
    }

    componentDidMount() {

    }

    render() {
        return (

            <form className="form-signin" onSubmit={this.handleSubmit} >
                <h3>Sign In</h3>

                <div className="form-group">
                    <label>Username</label>
                    <input type="text" className="form-control" autoComplete="off" 
                        id="input-username" name="UserName"
                        value={this.state.loginModel.UserName}
                        onChange={this.handleInputChange}
                        placeholder="Enter Username" />
                </div>

                <div className="form-group">
                    <label>Password</label>
                    <input type="password" className="form-control" autoComplete="off"
                        id="input-password" name="Password"
                        value={this.state.loginModel.Password}
                        onChange={this.handleInputChange}
                        placeholder="Enter Password" />
                </div>

                <button type="submit" className="btn btn-primary btn-block">Submit</button>
            </form>

        )
    }
}

export default login;

主页.js

import React from 'react';
import { NavLink } from "react-router-dom";

const home = (props) => {
    return (
        <div className="container-fluid">
            <div className="fill">
                <div className="row">
                    <div className="col-md-4 col-sm-12">
                        <div className="card">
                            <div className="card-body flex-fill">
                                <h5 className="card-title">Info 1</h5>
                                <p className="card-text">
                                    Details about Info 1
                                </p>
                            </div>
                            <div className="card-footer">
                                <NavLink exact={true} className="btn btn-primary btn-block" to='/info1'>Start</NavLink>
                            </div>
                        </div>
                    </div>

                    <div className="col-md-4 col-sm-12">
                        <div className="card">
                            <div className="card-body flex-fill">
                                <h5 className="card-title">Info 2</h5>
                                <p className="card-text">
                                    Details about Info 2
                                </p>
                            </div>
                            <div className="card-footer">
                                <NavLink exact={true} className="btn btn-info btn-block" to='/info2'>Browse</NavLink>
                            </div>
                        </div>
                    </div>

                    <div className="col-md-4 col-sm-12">
                        <div className="card">
                            <div className="card-body flex-fill">
                                <h5 className="card-title">Info 3</h5>
                                <p className="card-text">
                                    Details about Info 3
                                </p>
                            </div>
                            <div className="card-footer">
                                <NavLink exact={true} className="btn btn-success btn-block" to='/info3'>View</NavLink>
                            </div>
                        </div>
                    </div>
                </div>

            </div>
        </div>
    );
};

export default home;

我的方法很简单。应用程序在初始加载时显示 Home 组件。

在导航菜单中,我有一个链接可以导航到登录屏幕。

在登录屏幕中,我有一个登录表单,我可以在其中通过 API 调用验证用户名和密码。

我有多个问题,因为我仍在学习,但我觉得它们都是相关的,所以将它们一起添加到这里。

问题:

我希望我提供了足够的背景信息来说明我在这里想要实现的目标。我知道我需要进一步提高我在 React 之间如何进行数据通信的技能。更新:一直在阅读 Hooks,但我不确定如何在这里实现它。我是否需要将我的 JS 文件转换为使用函数式方法而不是类结构(ES6)?

格拉西亚斯。

标签: javascriptreactjs

解决方案


我使用 redux 来检查是否在登录时使用。因此,当应用程序在显示任何内容之前启动时,我会检查这一点。然后我有privateRoute

import React from "react";
import { Redirect, Route } from "react-router-dom";
import { useSelector } from "react-redux";

function PrivateRoute({ component: Component, ...props }) {
  const isAuthenticated = useSelector(state => state.User.isLogin);
  return (
    <Route
      render={props =>
        isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: "/login",
              state: { from: props.location }
            }}
          />
        )
      }
      {...props}
    />
  );
}

export default PrivateRoute;

如果用户已经登录,则定义 IsAuthenticated 组件以重定向主页:

import React from "react";
import { Redirect, Route } from "react-router-dom";
import { useSelector } from "react-redux";


function IsAuthenticated({ component: Component, ...props }) {
  const isAuthenticated = useSelector(state => state.User.isLogin)
  return (
    <Route
      {...props}
      render={props =>
        !isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: "/",
              state: { from: props.location }
            }}
          />
        )
      }
    />
  );
}

export default IsAuthenticated;

如果用户必须经过身份验证才能看到它们,请在此处定义我的路线:

    <Router>
      <Switch>
        {privateRoutes.map(({ path, component: Component }, idx) => (
          <PrivateRoute
            key={idx}
            exact
            path={path}
            component={() => (
              <SideNav>
                <Component />
              </SideNav>
            )}
          />
        ))}

        <IsAuthenticated exact path="/login" component={LoginPage} />
      </Switch>
    </Router>

这里我SideNav在我的页面中使用,您可以在Navbar组件中使用 redux 状态,并检查您是否可以显示或隐藏您想要的任何内容。或者,您可以为两种类型的页面定义两种布局。

如果您不想使用 redux,您可以定义状态App.js并将其传递给您的组件或使用反应上下文。

我希望我对你的问题有所帮助。


推荐阅读