首次登录后反应不重定向。但是在强制重定向并再次执行登录操作后重定向
React not redirecting after first login. But redirects after forcefully redirecting and doing a login action again
我有一个登录表单,点击它会调用以下函数。
总结,从 api 获取响应,如果有效,设置 cookie,然后使用 this.props.history.push()
重定向
handleSubmit(event) {
event.preventDefault();
const { email, password } = this.state;
axios({
method: 'post',
url: 'http://localhost:3003/login',
data: qs.stringify({ email, password }),
headers: {
'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
}
}).then(res => {
console.log("set cookie")
//the accestoken is set as a cookie in order to check routes
Cookies.set('accesstoken', res.data.accesstoken);
console.log("those are the props")
console.log(this.props);
this.props.history.push('/'); //the bug
}).catch(err => {
console.log(err)
})
}
但我面临的问题是,当我第一次登录时,重定向不起作用。它设置了所有的 cookie 和所有这些,但它从未真正将用户重定向到所需的目录。所以我被迫通过在浏览器搜索栏中输入我想要的路线来重定向自己。
这意味着一旦我强迫自己进入所需的目录,如果我注销(基本上删除 cookie),然后尝试再次登录。这次重定向成功了。
在我使用 ctrl+F5 清除所有缓存之前它会一直工作,这恰好导致了我在第一次登录时遇到的同样问题,所以我不得不再次手动重定向。
编辑:这是我的路线的样子
<BrowserRouter>
<Switch>
<Route exact path="/login" render={(props) => <LoginPage {...props}/>} />
<PrivateRoute authed={this.state.isAuthenticated} exact path="/" render={(props) => <RegisterPage />} />
</Switch>
</BrowserRouter>
这些是我的私人路线
import { Route } from 'react-router-dom';
从 'react' 导入 React;
从 'react-router';
导入 { 重定向}
export default ({ component: Component, render: renderFn, authed, ...rest }) =>{
//The privateroute is fed with the auth state of app.js and evaluates the render based on that . If flase always renders "/"
if (Component){
return (
<Route
{...rest}
render={props =>
authed === true ? (
<Component {...props} />
) : (
<Redirect to={{ pathname: '/login', state: { from: props.location } }} />
)
}
/>
)
} else {
return ( //Second case is for iframe based renders
<Route {...rest} render={props => authed === true ? renderFn(props) : <Redirect to={{ pathname: '/login', state: { from: props.location } }} /> } />
);
}
}
编辑 2:
app.js
constructor(props) {
super(props);
console.log("PROPS APPJS")
console.log(props)
//checks if user is autheticated within the system in order to manage routes
this.state = {
authenticationChecked: false,
isAuthenticated: false
}
}
componentDidMount() {
//calls the auth service to decide the auth state value
isAuthenticated().then((result) => {
if (result === true) {
this.setState({ isAuthenticated: true, authenticationChecked: true})
} else {
this.setState({ isAuthenticated: false, authenticationChecked: true})
}
});
}
login = (email, password) => {
var thiscomponent = this;
axios({
method: 'post',
url: 'http://localhost:3003/login',
data: qs.stringify({ email, password }),
headers: {
'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
}
}).then(res => {
console.log("set cookie")
//the accestoken is set as a cookie in order to check routes
Cookies.set('accesstoken', res.data.accesstoken);
console.log("those are the props")
console.log(this.props);
this.setState({ isAuthenticated: true }, () => {
thiscomponent.props.history.push('/'); //the bug
})
}).catch(err => {
console.log(err)
})
}
.
.
.
.
.
.
.
<BrowserRouter>
<Switch>
<PrivateRoute authed={this.state.isAuthenticated} exact path="/" render={(props) => <NewLandingPage login={this.login} {...props} exact />} />
</Switch>
</BrowserRouter>
登录页面
handleSubmit(event) {
const { email, password } = this.state;
this.props.login(email, password)
event.preventDefault();
}
编辑:登录页面道具
{"history":{"length":15,"action":"POP","location":{"pathname":"/login","search":"?email=test4%40test.com&password=test","hash":""}},"location":{"pathname":"/login","search":"?email=test4%40test.com&password=test","hash":""},"match":{"path":"/login","url":"/login","isExact":true,"params":{}}}
您在何时何地设置 isAuthenticated? – lehm.ro 7 分钟前
@lehm.ro 在我的 app.js 中,在 componentDidMount() 期间,默认 isAuthenticated 是 false – mouchin777 6 分钟前
然后一旦你重定向你必须使用 this.setState 来使它成为真的,否则你的私人路线将不会显示。但是为此你需要将真实状态传递到 app.js 然后触发一个函数来为 isAuthenticated true 设置状态,然后重定向到该路由
设置您的历史记录以在 app.js 中工作而不被 props 传递:
In order to make use of history
in the App
component use it with withRouter
. You need to make use of withRouter
only when your
component is not receiving the Router props
,
This may happen in cases when your component is a nested child of a
component rendered by the Router or you haven't passed the Router
props to it or when the component is not linked to the Router at
all and is rendered as a separate component from the Routes.
import React from 'react';
import { Route , withRouter} from 'react-router-dom';
import Dashboard from './Dashboard';
import Bldgs from './Bldgs';
var selectedTab;
class App extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
selectedTab = 0;
}
handleClick(value) {
selectedTab = value;
// console.log(selectedTab);
this.props.history.push('/Bldgs');
// console.log(this.props);
}
render() {
var _this = this;
return (
<div>
<Route exact path="/" render={(props) => <Dashboard {...props} handleClick={_this.handleClick} />} />
<Route path="/Bldgs" component={Bldgs} curTab={selectedTab} />
</div>
);
}
}
export default withRouter(App);
[Documentation][1] on withRouter
[1]: https://reacttraining.com/react-router/web/api/withRouter
变化 App.js
<Route exact path="/login" render={(props) => <LoginPage login={this.login} {...props} />} />
并添加
login = (email, password) => {
var thiscomponent = this;
axios({
method: 'post',
url: 'http://localhost:3003/login',
data: qs.stringify({ email, password }),
headers: {
'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
}
}).then(res => {
console.log("set cookie")
//the accestoken is set as a cookie in order to check routes
Cookies.set('accesstoken', res.data.accesstoken);
console.log("those are the props")
console.log(this.props);
this.setState({ isAuthenticated: true }, () => {
thiscomponent.props.history.push('/'); //the bug
})
}).catch(err => {
console.log(err)
})
}
并在登录页面
handleSubmit(event) {
const { email, password } = this.state;
this.props.login(email, password)
event.preventDefault();
}
我有一个登录表单,点击它会调用以下函数。
总结,从 api 获取响应,如果有效,设置 cookie,然后使用 this.props.history.push()
handleSubmit(event) {
event.preventDefault();
const { email, password } = this.state;
axios({
method: 'post',
url: 'http://localhost:3003/login',
data: qs.stringify({ email, password }),
headers: {
'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
}
}).then(res => {
console.log("set cookie")
//the accestoken is set as a cookie in order to check routes
Cookies.set('accesstoken', res.data.accesstoken);
console.log("those are the props")
console.log(this.props);
this.props.history.push('/'); //the bug
}).catch(err => {
console.log(err)
})
}
但我面临的问题是,当我第一次登录时,重定向不起作用。它设置了所有的 cookie 和所有这些,但它从未真正将用户重定向到所需的目录。所以我被迫通过在浏览器搜索栏中输入我想要的路线来重定向自己。
这意味着一旦我强迫自己进入所需的目录,如果我注销(基本上删除 cookie),然后尝试再次登录。这次重定向成功了。
在我使用 ctrl+F5 清除所有缓存之前它会一直工作,这恰好导致了我在第一次登录时遇到的同样问题,所以我不得不再次手动重定向。
编辑:这是我的路线的样子
<BrowserRouter>
<Switch>
<Route exact path="/login" render={(props) => <LoginPage {...props}/>} />
<PrivateRoute authed={this.state.isAuthenticated} exact path="/" render={(props) => <RegisterPage />} />
</Switch>
</BrowserRouter>
这些是我的私人路线
import { Route } from 'react-router-dom';
从 'react' 导入 React; 从 'react-router';
导入 { 重定向}export default ({ component: Component, render: renderFn, authed, ...rest }) =>{
//The privateroute is fed with the auth state of app.js and evaluates the render based on that . If flase always renders "/"
if (Component){
return (
<Route
{...rest}
render={props =>
authed === true ? (
<Component {...props} />
) : (
<Redirect to={{ pathname: '/login', state: { from: props.location } }} />
)
}
/>
)
} else {
return ( //Second case is for iframe based renders
<Route {...rest} render={props => authed === true ? renderFn(props) : <Redirect to={{ pathname: '/login', state: { from: props.location } }} /> } />
);
}
}
编辑 2:
app.js
constructor(props) {
super(props);
console.log("PROPS APPJS")
console.log(props)
//checks if user is autheticated within the system in order to manage routes
this.state = {
authenticationChecked: false,
isAuthenticated: false
}
}
componentDidMount() {
//calls the auth service to decide the auth state value
isAuthenticated().then((result) => {
if (result === true) {
this.setState({ isAuthenticated: true, authenticationChecked: true})
} else {
this.setState({ isAuthenticated: false, authenticationChecked: true})
}
});
}
login = (email, password) => {
var thiscomponent = this;
axios({
method: 'post',
url: 'http://localhost:3003/login',
data: qs.stringify({ email, password }),
headers: {
'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
}
}).then(res => {
console.log("set cookie")
//the accestoken is set as a cookie in order to check routes
Cookies.set('accesstoken', res.data.accesstoken);
console.log("those are the props")
console.log(this.props);
this.setState({ isAuthenticated: true }, () => {
thiscomponent.props.history.push('/'); //the bug
})
}).catch(err => {
console.log(err)
})
}
.
.
.
.
.
.
.
<BrowserRouter>
<Switch>
<PrivateRoute authed={this.state.isAuthenticated} exact path="/" render={(props) => <NewLandingPage login={this.login} {...props} exact />} />
</Switch>
</BrowserRouter>
登录页面
handleSubmit(event) {
const { email, password } = this.state;
this.props.login(email, password)
event.preventDefault();
}
编辑:登录页面道具
{"history":{"length":15,"action":"POP","location":{"pathname":"/login","search":"?email=test4%40test.com&password=test","hash":""}},"location":{"pathname":"/login","search":"?email=test4%40test.com&password=test","hash":""},"match":{"path":"/login","url":"/login","isExact":true,"params":{}}}
您在何时何地设置 isAuthenticated? – lehm.ro 7 分钟前
@lehm.ro 在我的 app.js 中,在 componentDidMount() 期间,默认 isAuthenticated 是 false – mouchin777 6 分钟前
然后一旦你重定向你必须使用 this.setState 来使它成为真的,否则你的私人路线将不会显示。但是为此你需要将真实状态传递到 app.js 然后触发一个函数来为 isAuthenticated true 设置状态,然后重定向到该路由
设置您的历史记录以在 app.js 中工作而不被 props 传递:
In order to make use of
history
in theApp
component use it withwithRouter
. You need to make use ofwithRouter
only when your component is not receiving theRouter props
,This may happen in cases when your component is a nested child of a component rendered by the Router or you haven't passed the Router props to it or when the component is not linked to the Router at all and is rendered as a separate component from the Routes.
import React from 'react'; import { Route , withRouter} from 'react-router-dom'; import Dashboard from './Dashboard'; import Bldgs from './Bldgs'; var selectedTab; class App extends React.Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); selectedTab = 0; } handleClick(value) { selectedTab = value; // console.log(selectedTab); this.props.history.push('/Bldgs'); // console.log(this.props); } render() { var _this = this; return ( <div> <Route exact path="/" render={(props) => <Dashboard {...props} handleClick={_this.handleClick} />} /> <Route path="/Bldgs" component={Bldgs} curTab={selectedTab} /> </div> ); } } export default withRouter(App);
[Documentation][1] on withRouter
[1]: https://reacttraining.com/react-router/web/api/withRouter
变化 App.js
<Route exact path="/login" render={(props) => <LoginPage login={this.login} {...props} />} />
并添加
login = (email, password) => {
var thiscomponent = this;
axios({
method: 'post',
url: 'http://localhost:3003/login',
data: qs.stringify({ email, password }),
headers: {
'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
}
}).then(res => {
console.log("set cookie")
//the accestoken is set as a cookie in order to check routes
Cookies.set('accesstoken', res.data.accesstoken);
console.log("those are the props")
console.log(this.props);
this.setState({ isAuthenticated: true }, () => {
thiscomponent.props.history.push('/'); //the bug
})
}).catch(err => {
console.log(err)
})
}
并在登录页面
handleSubmit(event) {
const { email, password } = this.state;
this.props.login(email, password)
event.preventDefault();
}