简体   繁体   English

如果用户登录或未登录,实现条件导航栏的策略

[英]Strategies to implementing a conditional Navbar if a user is logged in or not

Background : I am creating a very basic application with 4 different capabilities: Signup, Login, Searching, and Creating content.背景:我正在创建一个具有 4 种不同功能的非常基本的应用程序:注册、登录、搜索和创建内容。 As of right now, I can log in to users and prevent unauthorized users from going to protected routes.截至目前,我可以登录用户并防止未经授权的用户进入受保护的路线。 This is shown below in my Protected.js component.这在我的Protected.js组件中显示如下。 However, I am struggling to figure out a way to also conditionally display a login/logout button in my navigation bar located in my App.js .但是,我正在努力想办法在位于我的App.js的导航栏中有条件地显示登录/注销按钮

Followup Questions : Should I move the authentication logic out of my Login.js route and into my main App.js component and pass the state down?后续问题:我应该将身份验证逻辑从我的Login.js路由中移到我的主App.js组件中,然后将 state 向下传递吗? Wouldn't that be very inefficient, because every time I am rendering a new view, the App.js is performing another fetch with my backend API to verify if the user has a non-expired session?这不是非常低效吗,因为每次我渲染新视图时, App.js都会使用我的后端 API 执行另一次提取,以验证用户是否有未过期的 session? This might appear trivial to some, but I am having a difficult time wrapping my head around how to conditionally show a login/logout button efficiently.这对某些人来说可能看起来微不足道,但我很难理解如何有条件地有效地显示登录/注销按钮。 I have looked into Context API, so I would be open to some advice down that route if you feel necessary, but I am not familiar with Redux( I just began to React a week ago ).我已经查看了上下文 API,所以如果你觉得有必要,我愿意接受一些建议,但我不熟悉 Redux(我一周前才开始 React )。 I am looking for well-thought-out strategies, so I would greatly appreciate it if you could do your best to provide complete and coherent responses.我正在寻找经过深思熟虑的策略,因此如果您能尽最大努力提供完整和连贯的回复,我将不胜感激。 I really appreciate it.对此,我真的非常感激。

App.js应用程序.js

class App extends Component {
    render() {
        return(
            <Router>
                <div>
                    <Navbar bg="light" variant="light">
                        <Navbar.Brand href="#home">My Application</Navbar.Brand>
                        <Nav className="mr-auto">
                            <Link to="/signup" className="nav-link">Signup</Link>
                            <Link to="/login" className="nav-link">Login</Link>
                            <Link to="/feed" className="nav-link">Search</Link>
                            <Link to="/create-post" className="nav-link">Create</Link>
                        </Nav>
                        <Form inline>
                            <Button variant="outline-primary">Logout</Button>
                        </Form>
                    </Navbar>
                </div>
                <Switch>
                    <Route path = '/signup' component = {Signup} />
                    <Route path = '/login' component = {Login} />
                    <Route path = '/feed' component = {Feed} />
                    <ProtectedRoute path = '/create-post' component = {CreatePost} />
                </Switch>

            </Router>
        )
    }
}

Login.js登录.js

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

        this.state = {
            username: "",
            password: ""
        }

        this.handleChange = this.handleChange.bind(this)
        this.handleSubmitForm = this.handleSubmitForm.bind(this)
    }

    handleChange(event) {
        //console.log(event.target.name)
        this.setState({[event.target.name]: event.target.value})
    }

    handleSubmitForm() {
        const user = {
            username: this.state.username,
            password: this.state.password
        }

        const url = 'http://localhost:9000/api/login'

        fetch(url, {
            method: 'POST',
            credentials: 'include',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(user)
        })
        .then((response) => response.json())
        .then((data) => {
            if (data.status === 1) {
                this.props.history.push('/feed')
            }
            console.log(data)
        })
        .catch((error) => {
            console.log('Error', error)
        })
    }

    render() {
        return (
        <div>
            <Card className="card-login" style={{ width: '18rem' }}>
                <Card.Body>
                <Card.Title>Login</Card.Title>
                    <Form>
                        <Form.Group>
                            <Form.Control placeholder ="Username"
                                          name = "username"
                                          value = {this.state.username}
                                          onChange = {this.handleChange}/>
                        </Form.Group>
                        <Form.Group>
                            <Form.Control type ="password"
                                          placeholder="Password"
                                          name = "password"
                                          value = {this.state.password}
                                          onChange = {this.handleChange} />
                        </Form.Group>                   
                    <Button variant ="primary"
                            value="Submit"
                            onClick={this.handleSubmitForm}>Submit
                    </Button>
                    </Form>
                </Card.Body>
            </Card>         
        </div>)
    }
}

Protectedroute.js受保护的路由.js

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

        this.state = {
            isAuthenticated: false,
            isLoading: true
        }
        this.isAuthenticated = this.isAuthenticated.bind(this)
    }

    componentDidMount() {
        this.isAuthenticated()
    }

    isAuthenticated() {
        const url = 'http://localhost:9000/api/auth'
        fetch(url, {
            method: 'GET',
            credentials: 'include',
            headers: {
                'Content-Type' : 'application/json'
            }
        })
        .then((response) => response.text())
        .then((data) => {
            if (data === 'true') {
                this.setState({
                    isAuthenticated: true,
                    isLoading: false
                })
            } else {
                this.setState({
                    isAuthenticated: false,
                    isLoading: false
                })
            }
        })
        .catch((err) => {
            console.log('Error', err)
        })
    }
    render() {
        const Component = this.props.component
        if (this.state.isLoading === true) {
            return (<div>Loading</div>)
        }
        return(
            <Route render={(props) => this.state.isAuthenticated && !this.state.isLoading ? (<Component {...this.props}/>) : (<Redirect to ='/login' />)} />
        )
            
    }
}

api.js (Express Backend) api.js(快速后端)

router.post('/login', function(req,res,next) {
    const query1 = "SELECT * FROM users WHERE username = TRIM(?) AND pass = TRIM(?)"
    database.query(query1, [req.body.username, req.body.password])
    .then((result) => {
        if (result.length) {
            if (req.session.username) {
                res.json({'message': 'You are already logged in', 'status': 0})
            } else {
                req.session.username = req.body.username
                res.json({'message': 'You have successfully logged in', 'status': 1})
            }
        } else {
            if (req.session.username) {
                res.json({'message': 'You are already logged in', 'status': 0})
            } else {
                res.json({'message': 'Incorrect Credentials', 'status': 0})
            }
        }
    }).catch((err) => res.send(err))
})



router.get('/auth', (req, res, next) => {
    if (req.session.username) {
        res.send(true)
    } else {
        res.send(false)
    }
})

Well there is clear need for the global state and you can use React Context, Redux or even set auth state in App component, pass methods, which change state ie. Well there is clear need for the global state and you can use React Context, Redux or even set auth state in App component, pass methods, which change state ie. setAuth , as props to Login component. setAuth ,作为Login组件的道具。

class App extends Component {
  constructor(props) {
    super(props);
    this.setAuth = this.setAuth.bind(this);
    this.state = {
      isAuthenticated: false
    };
  }

  setAuth(value) {
    this.setState({
      isAuthenticated: value
    });
  }
<Route path='/login' component={() => <Login setAuth={this.setAuth} />} />

Should I move the authentication logic out of my Login.js route and into my main App.js component and pass the state down?我应该将身份验证逻辑从我的 Login.js 路由中移到我的主 App.js 组件中,然后将 state 向下传递吗? Wouldn't that be very inefficient, because every time I am rendering a new view, the App.js is performing another fetch with my backend api to verify if the user has a non-expired session?这不是非常低效吗,因为每次我渲染新视图时,App.js 都会使用我的后端 api 执行另一次提取,以验证用户是否有未过期的 session?

Did you mean the logic which happens in Protectedroute component?您是指Protectedroute组件中发生的逻辑吗? I would extract that to App component as you said because in a scenario正如您所说,我会将其提取到App组件中,因为在一个场景中

<ProtectedRoute path = '/create-post' component = {CreatePost} />
<ProtectedRoute path = '/post-list' component = {PostList} />
<ProtectedRoute path = '/update-post' component = {UpdatePost} />

It would check if user is authenticated multiple times when you want to get to '/update-post' section.当您想要进入'/update-post'部分时,它会检查用户是否经过多次身份验证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为登录用户显示不同的导航栏 - Display different navbar for logged user UseEffect 在用户登录时更新导航栏? - UseEffect to update navbar when user is logged in? 实施会话以保持用户登录状态,安全问题 - Implementing session to keep user logged, security issue 根据用户是否登录来显示不同导航栏的方法是什么? - What are the ways to show different navbar based on if the user logged or not? 根据用户是否登录在 React 中更改 Navbar 值的正确方法是什么? - What is the correct way to change Navbar values in React based on if user is logged in? React - 用户登录后如何在导航栏中隐藏注册/登录? - React - How to hide register/login in navbar once a user has logged in? 当用户未登录时显示导航栏。希望导航栏在用户拥有令牌后呈现 - NavBar displaying when user is not logged in. Want navbar to render after user has token Vue.js:无论用户是否登录,导航栏上的显示/隐藏按钮均基于Vuex商店状态 - Vue.js: Show/Hide buttons on navbar based on Vuex Store state when the user is logged in or not 一旦用户使用 React 和 Firebase 登录(从“登录”到“个人资料”),我如何更新我的导航栏? - How do I update my NavBar once a user is logged-in (from 'log in' to 'profile') using React & Firebase? React Conditional Render和Navbar - React Conditional Render and Navbar
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM