Метеор / Реакция: Перенаправление за пределы компонента как обратный вызов AccountsTemplates.logout () - PullRequest
0 голосов
/ 29 декабря 2018

Я пытаюсь интегрировать пакет meteor-useraccounts с React в мое приложение Meteor.Я пришел довольно далеко, но изо всех сил пытаюсь реализовать history.push() или эквивалент в качестве функции обратного вызова для AccountsTemplate.logout() - последняя является встроенным способом выхода пользователя из системы.

Конфигурацияфункция обратного вызова выполняется следующим образом:

AccountsTemplates.configure({
    onLogoutHook: myLogoutFunc
})

Но я не могу сделать это в «классе» React.Component.Поэтому мне нужно определить функцию обратного вызова, которая использует историю браузера, но находится вне области действия Компонентов, я думаю.

В случае нажатия Вход / Выход button , я нашел решение следующим образом:

class LogInOutButton extends Component {
    constructor(props) {
        super(props);

        this.state = {
            loggedIn: Meteor.userId() ? true : false,
            redirect: false
        }

        this.redirectToSignIn = this.redirectToSignIn.bind(this);

        window.logInOutButton = this;
    }

    redirectToSignIn() {
        if (!this.state.loggedIn && document.location.pathname !== "/signIn")
            this.setState({redirect: <Redirect to="/signIn" />});
    }

    render() {
        const { redirect } = this.state
        return (
            <li className="nav-item">
                {redirect}
                <a className="nav-link" href="#"
                    onClick={Meteor.userId() ? AccountsTemplates.logout : this.redirectToSignIn}>
                    {Meteor.userId() ? "Sign Out" : "Sign In"}
                </a>
            </li>
        )
    }
}

Как вы видите, я, например, пытался вызвать метод redirectToSignIn() извне, сделав его членомглобальный оконный объект.Неправильно и не работает:

var myLogoutFunc = () =>
    window.logInOutButton.redirectToSignIn();

Я также попробовал следующий подход:

var myLogoutFunc = withRouter(({history}) => 
    <div onLoad={history.push="/signIn"}>
    </div>
) 

Однако это не сработает, потому что withRouter нужноКомпонент как параметр, если я правильно понял?По крайней мере, вот как я пытаюсь объяснить следующую ошибку:

Exception in delivering result of invoking 'logout': TypeError: "props is undefined"

После прочтения этого в модуле withRouter:

var withRouter = function withRouter(Component) {
  var C = function C(props) {
     ...

Как бы вы решили это?

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018

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

Я склонен использовать iron: router и Blaze, а не React, но я думаю, что самое простое решение легкопереводить.Я опускаю это где-то на верхнем уровне моего клиентского кода:

Tracker.autorun(function() {
    const userDoc = Meteor.user();
    const loggingIn = Meteor.loggingIn();

    if(!userDoc && !loggingIn) {
        Router.go('/'); // Or comparable redirect command
    }
});

При загрузке страницы: если userDoc не определено (что означает, что пользователь не вошел в систему успешно) и loggingInневерно (имеется в виду, что Meteor не регистрирует пользователя при загрузке страницы), мы перенаправим пользователя на домашнюю страницу.

При выходе из системы: начиная с userDoc и loggingInоба являются реактивными источниками данных, эта функция autorun будет перезапущена каждый раз, когда изменяется любая из этих переменных.Поэтому, когда пользователь выходит из системы любым способом, userDoc перестанет быть определенным, условное выражение преобразуется в true и перенаправит пользователя на домашнюю страницу.

При входе в систему:Если вошедший в систему пользователь входит в систему или начинает входить, ничего не произойдет.Функция будет перезапущена, но принудительное автоматическое перенаправление в любое время может привести к усложнению изменения переменной userDoc или loggingIn.

0 голосов
/ 30 декабря 2018

Если честно, я отказался от идеи использовать пакет для создания пользовательского интерфейса для системы учетных записей.

Пакет meteor-useraccounts был создан для Blaze, и хотя вОфициальные документы Meteor рекомендуют обернуть шаблон {{> atForm }}, который преобразует формы для входа в систему, регистрации и т. д. в компонент React. Я обнаружил, что он вызывает несовместимость, особенно при обработке маршрутов.(Я использовал пакет gadicc:blaze-react-component для упаковки.) В конце концов я обнаружил, что пытаюсь понять этот черный ящик, который состоит из нескольких слоев, в том числе.еще один для предварительной стилизации bootstrap4.Например, я также не смог заставить работать проверку электронной почты.

Поэтому я решил сбросить все это и сам начал создавать весь пользовательский интерфейс и логику поверх Meteor Accounts и Meteor API паролей .

Теперь перенаправление чертовски просто, потому что я могу сделать это в своем собственном React.Component.Единственное, что вам нужно сделать, это import { withRouter } from 'react-router';, затем export default withRouter(LogInOutButton); и, наконец, вы можете использовать this.props.history.push("/signIn") для перенаправления:

import React, { Component } from 'react';
import { withRouter } from 'react-router';

class LogInOutButton extends Component {
    constructor(props) {
        super(props);

        this.state = {
            loggedIn: Meteor.userId() ? true : false,
        }

        this.redirectToSignIn = this.redirectToSignIn.bind(this);
    }

    redirectToSignIn() {
        if (this.state.loggedIn)
            Meteor.logout()
        if (document.location.pathname !== "/signIn")
            this.props.history.push("/signIn")
    }

    render() {
        return (
            <li className="nav-item">
                <a className="nav-link" href="#"
                    onClick={this.redirectToSignIn}>
                    {Meteor.userId() ? "Sign Out" : "Sign In"}
                </a>
            </li>
        )
    }
}

export default withRouter(LogInOutButton);

PS: (Просто мое мнение) Конечно, есть вещи, которые нужно решить при создании собственного пользовательского интерфейса / логики для системы учетных записей.Например, проверка формы.(Я решил построить поверх проверки HTML5, но добавлю свой собственный визуальный отклик с помощью bootstrap4 .)

Я полагаю, в случае с Meteor и Реагируют тамна данный момент просто нет рабочего пакета.Я попробовал их все, поверь мне.Все они были болью в заднице (при попытке интегрировать их с React) или недостаточно настраиваемыми.Если бы я потратил время на то, чтобы построить свой собственный с самого начала, я бы уже давно закончил.И самое замечательное в том, чтобы сделать это самостоятельно, вы знаете, как это работает, и можете легко улучшить и повторно использовать его позже.

Это также помогает поддерживать низкую зависимость, что я считаю крайне важным, потому что проект Meteor прогрессировал ибыстро меняется в последние годы.Проще поддерживать ваш проект в актуальном состоянии, когда вы знаете, что сделали.

...