Как я могу перенаправить на основе данных из моего API без перепрошивки компонента - React / Redux - PullRequest
1 голос
/ 24 февраля 2020

Я пишу небольшое приложение для ведения дел, и у меня возникают проблемы с перенаправлением пользователя на основе данных из бэкэнда. Приложение использует:

  • express-session для создания пользовательского сеанса на стороне сервера
  • connect-mongodb-session для хранения данных сеанса
  • react-redux для приложения управление состоянием

Когда пользователь входит в систему, свойство модели User с именем isLoggedIn устанавливается на true. Это значение используется для перенаправления пользователя в компонент LandingPage, где он может создавать новые задачи. Это нормально, но проблема в том, что, если целевая страница обновляется, значение для isLoggedIn не поступило из бэкэнда до визуализации LandingPage. Это приводит к тому, что пользователь перенаправляется на страницу входа, затем поступают данные, а затем они снова перенаправляются на целевую страницу.

«Вспыхивающая» страница входа чрезвычайно раздражает, и я не могу найти какой-либо способ обойти это. Я попытался сохранить логическое значение isLoggedIn в localStorage, и это сработало замечательно, но, конечно, это лишает смысла использование сеанса на стороне сервера?

Вот некоторые фрагменты из моего кода, спасибо

Приложение. js

import { getUser } from "./redux/actions/auth";

const App = withRouter(({ user, data }) => {
    useEffect(() => {
        store.dispatch(getUser()); // user data loaded every time app re-renders
    }, []);

    return (
        <Provider store={store}>
            <Router>
                <div className='my-app'>
                    <Switch>
                        <Route exact path='/login' component={Login} />
                        <Private
                            isLoggedIn={isLoggedIn}
                            path='/landing'
                            component={LandingPage}
                        />
                    </Switch>
                </div>
            </Router>
        </Provider>
    );

const Private = ({ isLoggedIn, component: Component, ...rest }) => {
    return (
        <Route
            {...rest}
            render={props =>
                isLoggedIn ? (
                    <Component {...props} />
                ) : (
                    // I think the problem is here - because isLoggedIn is not available from the backend 
                    // call yet, so login page gets rendered before the data arrives
                    <Redirect to='/login' {...props} /> 
                )
            }
        />
    );
};

Вход. js

render() {
    const { user } = this.props;

    if (user.isLoggedIn) return <Redirect to='/landing' />; // user sent to landing if they are logged in

    return (... login form jsx)
}

Login.propTypes = {
    user: PropTypes.object
};

const mapStateToProps = state => ({
    user: state.auth.user
});

export default connect(mapStateToProps)(Login);

getUser. js

export const getUser = () => async dispatch => {
    try {
        const response = await axios.get("/api/user");
        dispatch({
            type: LOADED_USER,
            payload: response.data
        });
    } catch (error) {
        dispatch({
            type: LOAD_USER_FAILED
        });
    }
};

getUserReducer. js

const initialState = {
    user: {}
};

export default function(state = initialState, action) {
    const { type, payload } = action;
    switch (type) {
        case LOGIN_SUCCEEDED:
        case LOADED_USER:
            return {
                ...state,
                user: payload
            };
        case LOGIN_FAILED:
        case LOAD_USER_FAILED:
            return {
                ...state,
                user: {}
            };
        default:
            return state;
    }
}

1 Ответ

1 голос
/ 25 февраля 2020

Так что есть несколько способов сделать это. Один из способов - создать аутентифицированный маршрут, единственной целью которого является проверка кулинарного сеанса ie, например, /me.

Если пользователь уже вошел в систему, браузер должен иметь действительный сеанс как повар ie. Это будет означать, что /me можно запросить с 200. Если сессия истекла, вы получите 401. В случае 401 вы просто перенаправляете обратно на страницу входа.

Есть много способов сообщить, что это происходит и с пользователем. Один из способов заключается в том, чтобы иметь некоторое состояние в локальном хранилище, как вы уже делаете, и просто предполагать, что пользователю разрешено переходить на целевую страницу. Вы не будете загружать какие-либо конфиденциальные данные в любом случае, так как данные должны находиться за аутентифицированными конечными точками.

В случае любых 401-х вы можете перенаправить вход в систему или показать ошибку пользователю, говорящему что-то вроде «Появляется срок сеанса истек, нажмите здесь, чтобы снова войти в систему. ".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...