我正开始学习React JS。在我的项目中,我需要创建两条路由,一条用于用户身份验证,另一条需要重定向到登录页面。
我已经使用React Router创建了这个结构。这是路线的容器:
export const history = createHistory();
class AppContainer extends Component {
componentDidMount(){
this.props.checkUserExist();
}
render() {
return (
<Router history={history}>
<Switch>
<PrivateRoute path="/" component={Welcome} exact={true}/>
<PrivateRoute path="/friends" component={Friends}/>
<PublicRoute path="/login" component={Login}/>
<PrivateRoute path="/loves" component={Loves}/>
<Route component={NotFoundPage}/>
</Switch>
</Router>
);
}
}
const mapDispatchToProps = (dispatch) => {
return {
checkUserExist: () => dispatch(checkUser())
};
};
export default connect(undefined,mapDispatchToProps)(AppContainer);
这些是动作:
export const checkUser = () => (dispatch) => {
dispatch({
type: CHECKING_USER,
payload: {
loading:true,
isAuth:false
}
});
from(axios.get('https://mysite.private.com/userExist', {
withCredentials: true
})).subscribe((result) => {
console.log('result:', result);
result.data == null
? dispatch({
type: USER_NOT_EXIST,
payload: {
isAuth: false,
loading:false
}
})
: dispatch({
type: USER_EXIST,
payload: {
isAuth: true,
user:result.data,
loading: false
}
});
}, (error) => dispatch({
type: USER_CHECKING_ERROR,
payload: {
loading: false,
isAuth:false,
error
}
}));
};
和减速器:
const user = (state = {}, action) => {
switch (action.type) {
case CHECKING_USER:
return{
...state,
...action.payload
};
case USER_EXIST:
return {
...state,
...action.payload
};
case USER_NOT_EXIST:
return {
...state,
...action.payload
};
case USER_CHECKING_ERROR:
return {
...state,
...action.payload
}
default:
return state;
}
};
export default user;
在Redux中。
最后,这是PrivateRoute
的声明:
import React from 'react';
import { connect } from 'react-redux';
import { Route, Redirect } from 'react-router-dom';
export const PrivateRoute = ({
isAuthenticated,
component: Component,
...rest
}) => (
<Route {...rest} component={(props) => (
isAuthenticated ? (
<div><Component {...props} /></div>
) : (
<Redirect to="/login" />
)
)}/>
);
const mapStateToProps = (state) => ({
isAuthenticated: state.user.isAuth
});
export default connect (mapStateToProps)(PrivateRoute);
和PublicRoute
:
import React from 'react';
import { connect } from 'react-redux';
import { Route, Redirect } from 'react-router-dom';
export const PublicRoute = ({
isAuthenticated,
component: Component,
...rest
}) => (
<Route {...rest} component={(props) => (
isAuthenticated ? (
<Redirect to="/" />
) : (
<Component {...props} />
)
)}/>
);
const mapStateToProps = (state) => ({
isAuthenticated: state.user.isAuth
});
export default connect (mapStateToProps)(PublicRoute);
错误是这样的:例如,在加载'/friends'
时,它先加载到Login
组件,然后再加载到'/'
,然后加载到Welcome
组件中。这可能是因为它在checkUserExist()
完成之前渲染。
我的问题是:有办法避免吗?也许使用超时或等待ajax调用完成。
谢谢您的回答。
答案 0 :(得分:0)
import React from 'react';
import { connect } from 'react-redux';
import { Route, Redirect } from 'react-router-dom';
export const PublicRoute = ({
isAuthenticated,
component: Component,
...rest
}) => {
isAuthenticated ? localStorage.setItem("red", "") : localStorage.setItem(history.location.pathname) ;
return (<Route {...rest} component={(props) => (
isAuthenticated ? (
<Redirect to="/" />
) : (
<Component {...props} />
)
)}/>);
};
const mapStateToProps = (state) => ({
isAuthenticated: state.user.isAuth
});
export default connect (mapStateToProps)(PublicRoute);
export const history = createHistory();
class AppContainer extends Component {
componentDidMount(){
this.props.checkUserExist();
}
redirectMe = () => {
const redirect= localStorage.getItem("red");
localStorage.getItem("red", "");
if(redirect !== "")
return <Redirect to={redirect} />
}
render() {
redirectMe()
return (
<Router history={history}>
<Switch>
<PrivateRoute path="/" component={Welcome} exact={true}/>
<PrivateRoute path="/friends" component={Friends}/>
<PublicRoute path="/login" component={Login}/>
<PrivateRoute path="/loves" component={Loves}/>
<Route component={NotFoundPage}/>
</Switch>
</Router>
);
}
}
const mapDispatchToProps = (dispatch) => {
return {
checkUserExist: () => dispatch(checkUser())
};
};
export default connect(undefined,mapDispatchToProps)(AppContainer);
我做了什么?
我在私有路由中添加了一个条件,即如果用户未通过身份验证并且正在寻找私有路由,则被调用的url将存储在本地存储中。
由于AppRouter每次都会渲染,因此它将检查是否找到了任何URL的本地存储,它将移动到该URL并清除本地存储。
注意:如果这不起作用,则在状态中创建一个变量,然后在AppRouter.js中连接该状态变量,而不是在该位置中设置为localstorage set状态。