React登录成功后关闭Login组件加载Servicedesk组件的最优方案
Hey there! Let's break down how to properly switch from your Login component to Servicedesk after a successful login—and ditch that direct DOM manipulation for React-friendly practices. Your idea of using a "return-style" close makes sense if you're thinking of browser navigation, but let's cover the two best approaches depending on your app structure.
First, let's note: your current code uses document.getElementById to toggle classes, which goes against React's core principle of state-driven views. We should let React handle rendering based on state instead of manually modifying the DOM.
Option 1: Parent Component Controls Render State (Best for Simple Apps)
The most React-native approach is to lift the login state up to a parent component (like App.js). The parent will decide whether to render Login or Servicedesk based on whether the user is logged in.
Parent Component (App.js)
import React, { Component } from 'react'; import Login from './Login'; import Servicedesk from './Servicedesk'; class App extends Component { constructor(props) { super(props); this.state = { isLoggedIn: false, user: null }; this.handleLoginSuccess = this.handleLoginSuccess.bind(this); } handleLoginSuccess(username, email) { // Update state to trigger component switch this.setState({ isLoggedIn: true, user: { username, email } }); // Save user data to sessionStorage sessionStorage.setItem('loginSessionUsername', username); sessionStorage.setItem('loginSessionEmail', email); } render() { const { isLoggedIn, user } = this.state; return ( <div className="app-container"> {isLoggedIn ? ( <Servicedesk user={user} /> ) : ( <Login onLoginSuccess={this.handleLoginSuccess} /> )} </div> ); } } export default App;
Updated Login Component
import React, { Component } from 'react'; class Login extends Component { constructor(props) { super(props); this.state = { email: '', password: '' }; this.handleClick = this.handleClick.bind(this); } handleClick(event) { event.preventDefault(); // Replace this with your actual login API call const { email, password } = this.state; const username = email.split('@')[0]; // Example: use email prefix as username // Notify parent component of successful login this.props.onLoginSuccess(username, email); } render() { const { email, password } = this.state; return ( <div className='setVisible'> <div> <label>Emailadres</label> <input type='text' placeholder='je email' value={email} onChange={ev => this.setState({email: ev.target.value})} /> <label>Wachtwoord</label> <input type='password' placeholder='je wachtwoord' value={password} onChange={ev => this.setState({password: ev.target.value})} /> <br /> <button onClick={this.handleClick}>Submit</button> </div> </div> ); } } export default Login;
Why this works:
- Follows React's one-way data flow: the parent holds the source of truth for login state, and child components react to changes.
- No manual DOM changes—React automatically re-renders the correct component when
isLoggedInupdates. - Easy to debug and maintain, since all state logic lives in one place.
Option 2: React Router for Navigation (Best for Multi-Page SPAs)
If your app has multiple pages, using React Router makes sense. This lets you use browser navigation (like the back button) to "close" the Login page and return to it later—exactly matching your idea of a "return-style" close.
First, install React Router (v5 is used here; adjust if you're on v6):
npm install react-router-dom@5
Router Setup (App.js)
import React, { Component } from 'react'; import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom'; import Login from './Login'; import Servicedesk from './Servicedesk'; class App extends Component { // Check if user is logged in via sessionStorage isLoggedIn() { return !!sessionStorage.getItem('loginSessionUsername'); } render() { return ( <Router> <Switch> {/* Login Route: Redirect to Servicedesk if already logged in */} <Route path="/login"> {this.isLoggedIn() ? <Redirect to="/servicedesk" /> : <Login />} </Route> {/* Servicedesk Route: Redirect to Login if not logged in */} <Route path="/servicedesk"> {this.isLoggedIn() ? <Servicedesk /> : <Redirect to="/login" />} </Route> {/* Default redirect to Login */} <Redirect from="/" to="/login" /> </Switch> </Router> ); } } export default App;
Updated Login Component with Routing
import React, { Component } from 'react'; import { withRouter } from 'react-router-dom'; class Login extends Component { constructor(props) { super(props); this.state = { email: '', password: '' }; this.handleClick = this.handleClick.bind(this); } handleClick(event) { event.preventDefault(); const { email, password } = this.state; // Replace with your actual login logic const username = email.split('@')[0]; // Save user data to sessionStorage sessionStorage.setItem('loginSessionUsername', username); sessionStorage.setItem('loginSessionEmail', email); // Navigate to Servicedesk page this.props.history.push('/servicedesk'); } render() { const { email, password } = this.state; return ( <div className='setVisible'> <div> <label>Emailadres</label> <input type='text' placeholder='je email' value={email} onChange={ev => this.setState({email: ev.target.value})} /> <label>Wachtwoord</label> <input type='password' placeholder='je wachtwoord' value={password} onChange={ev => this.setState({password: ev.target.value})} /> <br /> <button onClick={this.handleClick}>Submit</button> </div> </div> ); } } // Inject routing history via higher-order component export default withRouter(Login);
Why this works:
- Uses browser navigation: after login, users are taken to
/servicedesk, and clicking the back button will return them to/login(which will redirect back if they're still logged in). - Adds route protection: users can't access
/servicedeskwithout logging in, and can't access/loginif they are logged in. - Scales well for larger apps with more pages.
Why Avoid Direct DOM Manipulation?
- It breaks React's virtual DOM diffing process, which can lead to inconsistent state and hard-to-debug bugs.
- It's not maintainable—other developers won't expect DOM changes outside of React's state system.
- State-driven rendering is the standard React pattern, making your code more predictable.
内容的提问来源于stack exchange,提问作者JJNL77

