Я пытаюсь реализовать частные, защищенные и публичные c маршруты для проекта, над которым я работаю. На каждой странице refre sh я отправляю своего создателя действия setUserAsyn c () в componentDidMount в моем приложении. js, который вызывает мой бэкэнд и запрашивает информацию о пользователе на основе токена, назначенного при входе в систему или регистрации. SetUserAsyn c устанавливает пользователя и переключает состояние isAuthenticated в true, если пользователь принят. Затем я использую состояние isAuthenticated, чтобы определить, какой компонент следует рендерить или перенаправлять в моих личных и опубликованных маршрутах c.
Но проблема, с которой я сталкиваюсь, заключается в том, что всякий раз, когда я пытаюсь получить доступ к какому-либо частному или защищенному маршруту, троичный оператор немедленно запускается на основе начального состояния isAuthenticated, которое является ложным. Следовательно, на частном маршруте, таком как / dashboard, я перейду в / signin, поскольку isAuthenticated изначально имеет значение false до тех пор, пока setUserAsyn c () в componentDidMount приложения не установит значение true. js. Затем из / signin я перенаправлен обратно на / dashboard, так как / signin является защищенным маршрутом и возвращает меня к / dashboard, так как isAuthenticated к тому времени наконец становится истинным.
Как я могу сделать так, чтобы мои маршруты на refre sh дождитесь завершения вызова API, прежде чем что-либо делать. Я видел, как многие люди применяют один и тот же поток, и он прекрасно работает для них, но я не знаю, что я делаю неправильно.
//App.js
class App extends React.Component {
componentDidMount() {
const { setUserAsync, token, tokenExpiry } = this.props;
token ? setUserAsync(token) : null
}
render() {
return (
<Switch>
<PublicRoute exact path="/" component={Home} />
<PublicRoute exact path="/about-us" component={AboutUs} />
<PublicRoute exact path="/contact-us" component={ContactUs} />
<PublicRoute exact path="/privacy-policy" component={PrivacyPolicy} />
<PublicRoute exact path="/terms-of-use" component={TermsOfUse} />
<ProtectedRoute exact path="/signin" component={SignIn} />
<ProtectedRoute exact path="/signup" component={SignUp} />
<PrivateRoute exact path="/dashboard" component={Dashboard} />
<PrivateRoute exact path="/all-leads" component={AllLeads} />
</Switch>
)};
const mapStateToProps = createStructuredSelector({
token: selectUserToken,
tokenexpiry: selectTokenExpiry
});
const mapDispatchToProps = dispatch => ({
setUserAsync: (token) => dispatch(setUserAsync(token))
});
export default connect(mapStateToProps, mapDispatchToProps)(App);
//PrivateRoute - dashboard
const PrivateRoute = ({ component: Component,isAuthenticated, ...rest }) => {
return (
<Route
{...rest}
render={props =>
isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{ pathname: "/signin", state: { from: props.location } }}
/>
)
}
/>
)
};
const mapStateToProps = createStructuredSelector({
isAuthenticated: selectIsUserAuthenticated,
});
export default connect(mapStateToProps)(PrivateRoute);
//ProtectedRoute - signin & signup
const ProtectedRoute = ({component: Component, isAuthenticated, isFetching, ...rest}) => {
return !isFetching ? (
<Route
{...rest}
render={(props) =>
isAuthenticated
? <Redirect to={{pathname: '/dashboard', state: {from: props.location}}} />
: <Component {...props} /> }
/>
)
: null
}
const mapStateToProps = createStructuredSelector({
isAuthenticated: selectIsUserAuthenticated,
isFetching: selectIsFetching
});
export default connect(mapStateToProps)(ProtectedRoute);
//User reducer
const INITIAL_STATE = {
isAuthenticated: false,
currentUser: null
};
const UserReducer = (state = INITIAL_STATE, action) => {
const { type, payload } = action;
switch (type) {
case UserActionTypes.FETCH_USER_SUCCESS: {
return {
...state,
isAuthenticated: true,
currentUser: payload
};
}
case UserActionTypes.FETCH_USER_ERROR: {
return {
...state,
isAuthenticated: false,
currentUser: null
};
}
default:
return state;
}
};
export default UserReducer;