我正在尝试在用户成功登录(在Login.js内)后使用React Router进行简单的重定向,并阻止用户重新访问登录页面(在index.js内)。
在Login.js中,我在登录按钮标签中有onSubmit={this.handleSubmit}
,并且有handleSubmit(e)
函数可以重定向。我在线上尝试了其他一些解决方案,但我认为我对<Redirect/>
组件的用法的理解是错误的。
在index.js中,我有一个条件可以测试用户是否已登录,并(较差)警告用户为什么他们无法访问所需页面。我在YouTube视频中看到了这一点,但不确定这是否是获得理想效果的最佳方法。
当前,当我成功登录时,警报You can't login if you are logged in!
被设置为关闭,但是我显然不希望成功登录后立即关闭警报,我希望重定向首先触发。如果我在括号中交换两者,React会引发错误。
如何成功登录后立即触发重定向,但不发送警报You can't login if you are logged in!
?
Login.js组件:
import React, { Component } from 'react';
import fire from '../config/Fire.js';
import { Link, Redirect } from 'react-router-dom';
import PasswordMask from 'react-password-mask';
export default class Login extends Component {
constructor(props) {
super(props);
this.login = this.login.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.signup = this.signup.bind(this);
this.state = {
email: '',
password: ''
};
}
handleChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
<Redirect to="/ticket-list"/>;
}
login(e) {
e.preventDefault();
fire.auth().signInWithEmailAndPassword(this.state.email, this.state.password).catch((error) => {
alert(error);
});
}
signup(e){
e.preventDefault();
fire.auth().createUserWithEmailAndPassword(this.state.email, this.state.password).catch((error) => {
alert(error);
})
}
render() {
return (
<div className="m-container">
<h1>Login</h1>
<hr/>
<div className="m-container">
<form onSubmit={this.submitForm}>
<div>
<label for="exampleInputEmail1">Email address: </label>
<br/>
<input
value={this.state.email}
onChange={this.handleChange}
type="text"
name="email"
id="exampleInputEmail1"
placeholder="you@email.com" />
</div>
<div>
<label for="exampleInputPassword1">Password: </label>
<br/>
{/* Margin issue when showing and hiding password */}
<PasswordMask
value={this.state.password}
onChange={this.handleChange}
type="password"
name="password"
id="exampleInputPassword1"
placeholder="**********"
/>
</div>
<br/>
<button
type="submit"
className="button"
onClick={this.login}
onSubmit={this.handleSubmit}>Login</button>
<Link className="button-inv" to="/register">Register</Link>
</form>
</div>
</div>
);
}
}
index.js组件:
import React, { Component } from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';
import Home from './Home';
import Technician from './Technician';
import About from './About';
import Register from './Register';
import Login from './Login';
import TicketList from './TicketList';
export default class Routes extends Component {
render() {
return (
<Switch>
<Route path="/" exact component={Home} />
<Route path="/technician" exact component={Technician} />
<Route path="/about" exact component={About} />
<Route path="/register" exact render={()=>(
this.props.user ? (alert("You can't register if you are logged in!"), (<Redirect to="/"/>)) : (<Register/>)
)} />
<Route path="/login" exact render={()=>(
this.props.user ? (alert("You can't login if you are logged in!"), (<Redirect to="/ticket-list"/>)) : (<Login/>)
)} />
<Route path="/ticket-list" exact render={()=>(
this.props.user ? (<TicketList/>) : (alert("You must log in to visit this page."), (<Redirect to="/login"/>))
)} />
</Switch>
);
}
};
App.js :
import React, { Component } from 'react';
import { BrowserRouter } from 'react-router-dom';
import Routes from './routes';
import fire from './config/Fire.js';
// CSS
import './assets/css/App.css';
import './assets/css/Header.css';
import './assets/css/Footer.css';
// Components
import Header from './components/Header';
import Footer from './components/Footer';
class App extends Component {
constructor(props){
super(props);
this.state = {
user:{},
}
}
//When component is done rendering for the first time
componentDidMount(){
this.authListener();
}
// If user logs in (if) or out (else) this is called
authListener() {
fire.auth().onAuthStateChanged((user) => {
//console.log(user);
if (user) {
this.setState({ user });
} else {
this.setState({ user: null });
}
});
}
render() {
return (
<BrowserRouter>
<div className="wrapper">
<Header user={this.state.user} />
<div className="body">
<Routes user={this.state.user} />
</div>
<Footer />
</div>
</BrowserRouter>
);
}
}
export default App;
答案 0 :(得分:2)
要解决您的问题,您必须为Login
/ Register
创建单独的组件,并根据用户的需要发出警报和重定向。您将需要withRouter
库中名为react-router
的高阶组件。
登录容器:
class LoginContainer extends Component {
constructor(props) {
super(props)
if (props.user) {
alert("You can't login if you are logged in!")
props.history.push('/ticket-list')
}
}
render() {
return <Login />;
}
}
export default withRouter(LoginContainer)
然后像下面这样在您的Routes
中使用它:
<Route path="/login" render={()=> <LoginContainer user={this.props.user} />} />
与Register
相同,或者您可以制作一个并获得alertMessage
和redirectTo
之类的参数,并使用它们代替硬编码值。
此外,我建议您将auth HoC用于您的私有路由,未经身份验证就无法访问。
我更喜欢使用新的上下文API来共享用户,本地化等实体,因此这里是一个示例,说明如何使用React PrivateRoute
API来制作Context
。
App.js
...
export const UserContext = React.createContext();
...
class App extends Component {
state = {
user: null
}
componentDidMount() {
this.authListener();
}
authListener() {
fire.auth().onAuthStateChanged(user => {
if (user) {
this.setState({ user });
}
});
}
render() {
<UserContext.Provider value={this.state}>
<BrowserRouter>
// another things Switch etc
...
</BrowserRouter>
</UserContext.Provider>
}
}
PrivateRoute.jsx
import React, { Component } from 'react';
import { Route, Redirect } from 'react-router-dom'
import { UserContext } from './App'
const PrivateRoute = ({ component: ComposedComponent, ...rest }) => {
class Authentication extends Component {
handleRender = props => {
if (!this.props.user) {
return <Redirect to="/login" />
} else {
return <ComposedComponent user={this.props.user} {...props} />
}
}
render() {
return (
<Route {...rest} render={this.handleRender} />
);
}
}
return (
<UserContext.Consumer>
{
({ user }) => <Authentication user={user} />
}
</UserContext.Consumer>
)
};
export default PrivateRoute
然后,如果您不想显示未经身份验证的页面,则可以使用PrivateRoute
代替Route
。
import PrivateRoute from './PrivateRoute'
...
// all of the component code
render() {
...
<Switch>
<PrivateRoute path="/ticket-list" component={<TicketList />} />
</Switch>
...
}
希望有帮助!祝你好运!
答案 1 :(得分:2)
如果有人仍在寻找另一个答案,则可以执行以下操作:
public static void main(String[] args) throws Exception {
JSONParser jsonparser = new JSONParser();
try( FileReader reader = new FileReader("test.json"))
{
Object obj = jsonparser.parse(reader);
ObjectMapper mapper = new ObjectMapper();
JSONArray List = (JSONArray) obj;
JsonNode root = mapper.readTree(reader);
for (JsonNode jsonNode : root) {
if (jsonNode instanceof ObjectNode) {
ObjectNode o = (ObjectNode) jsonNode;
o.remove("UserID");
}
}
System.out.println(List);
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
注意:为简便起见,我删除了不相关的代码。在此示例中,成功的LOGIN api调用中,返回的响应正文包含import { Redirect } from 'react-router-dom';
render() {
let isSuccess, message;
if (this.props.response.hasOwnProperty('response')) {
message = this.props.response.response.data.message;
console.log(this.props);
isSuccess = this.props.response.response.data.success;
if (isSuccess) {
localStorage.setItem('jwt', JSON.stringify(this.props.response.response.data.token));
}
}
return (
<div>
{!isSuccess ? <div>{message}</div> : <Redirect to='/admin/dashboard' />}
</div>
);
}
,在失败的LOGIN api调用中,返回的响应正文包含{ success: true, token: <jwt> }
答案 2 :(得分:1)
如官方文档所述,您应该创建一个专用路由器
这是我如何使用本地存储来实现该示例的示例,以查看用户数据是否存在,然后如果数据不存在,则重定向回登录页面。这可以在您所有的组件中重复使用!
import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom';
import Login from './views/login';
import Supportedmodels from './views/dashboard/supported-models';
const PrivateRoute = ({ component: Component, ...rest }) =>
(
<Route {...rest} render={props =>
(
localStorage.getItem('user') ? <Component {...props} /> : <Redirect to={{pathname: '/login'}}/>
)}/>
);
function App()
{
return (
<Router>
<Switch>
<PrivateRoute path="/" component={Supportedmodels} exact />
<Route path="/login" component={Login} />
</Switch>
</Router>
);
}
要了解更多信息,请点击链接https://reacttraining.com/react-router/web/example/auth-workflow
答案 3 :(得分:0)
您可以使用:
<Redirect push to="/somewhere/else"/>
答案 4 :(得分:0)
import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom';
import Login from './views/login';
import Supportedmodels from './views/dashboard/supported-models';
const PrivateRoute = ({ component: Component, ...rest }) =>
(
<Route {...rest} render={props =>
(
localStorage.getItem('user') ? <Component {...props} /> : <Redirect to={{pathname: '/login'}}/>
)}/>
);
function App()
{
return (
<Router>
<Switch>
<PrivateRoute path="/" component={Supportedmodels} exact />
<Route path="/login" component={Login} />
</Switch>
</Router>
);
}