Реагировать на границы ошибок для аутентификации пользователя (с использованием приставки) - зачем нужен локальный setState? - PullRequest
0 голосов
/ 18 февраля 2019

Проблема

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

У меня есть«рабочее» решение, но я не понимаю, почему мой взлом заставил его работать Может ли кто-нибудь помочь мне разобрать, что я делаю неправильно?

Общая теория того, что я делаю

Насколько я понимаю ...

У меня есть компонент, который находится в моем приложении и оборачивает основной блок контента (не основной nav tho).Он использует componentDidCatch, чтобы поймать любой accessDenied брошенный и перенаправить пользователя на экран входа в систему.

У меня есть HOC, который может использовать любой контейнер, чтобы ограничиться только авторизованными пользователями.Он проверяет текущее состояние isAuthenticated в магазине и перенаправляет пользователя на страницу входа, если это не так.

Если вы попытаетесь перейти на страницу с ограниченным доступом, HOC (EnsureAuthenticatedConnector) выдает ошибку, которая всплывает и перехватывается AuthBarrier.

Так в чем проблема?

Как показано ниже, этот код работает.Но у меня локальное состояние установлено на AuthBarrier.Это ничего не делает.

Если я удаляю this.setState({ hasError: true });, он ломается.

URL-адрес изменяется, отображается панель навигации (она находится за пределами границы ошибки), но основной экран просто белый.

Страница входа никогда не появляется.Что делает setState, не используется?

Мой код

AuthBoundary.js - Часть 1 Функция проверки подлинности

МойHOC ожидает компонент, однако так же connect, и оба они являются функциями ( ref ).Чтобы решить эту проблему, мы объединяем их с подключением.

EnsureAuthenticatedConnector должен стоять на первом месте (так как нам нужен доступ к реквизиту, а не к элементу его обертки), поэтому у нас есть функция двойной стрелки, поэтому она получает доступ как к компоненту, так и к реквизиту (эточасть, в которой я опасен).

const accessDenied = {};

const EnsureAuthenticatedConnector = ComposedComponent => props => {
    if (!props.isAuthenticated) {
        console.log("This console fires twice, but only when an error is thrown in here.");
        throw accessDenied;
    }
    return <ComposedComponent {...props} />;
};

const mapStateToPropsEnsureAuth = state => {
    return {
        isAuthenticated: state.auth.isAuthenticated,
    };
};

const connectedEnsureAuth = compose(
    // These are both single-argument HOCs
    connect(
        mapStateToPropsEnsureAuth,
        null
    ),
    EnsureAuthenticatedConnector
);

...
export { ConnAuthBarrier, connectedEnsureAuth };

AuthBoundary.js - Часть 2 Auth Catching element

class AuthBarrier extends Component {
    static propTypes = {
        dispatch: PropTypes.func.isRequired,
        children: PropTypes.node.isRequired
    };

    constructor(props) {
        super(props);
        this.state = {
            hasError: false
        };
    }

    // Catch child errors if they're access denied.
    componentDidCatch(error) {
        if (error === accessDenied) {
            // For reasons unknown removing this line
            // causes this to break.
            // This makes no sense, because I don't use this anywhere...
            this.setState({ hasError: true });
            this.props.dispatch(push("/login"));
        }
    }
    render() {
        // We do nothing clever always render the 
        // children
        return this.props.children;
    }
}
const ConnAuthBarrier = connect()(AuthBarrier);

RestrictedPage.js

import { connectedEnsureAuth} from "components/AuthBoundary";

const RestrictedPage = () => {
    return (
        <div>
            <h1>This content is TOP SECRET</h1>
        </div>
    );
};

RestrictedPage.displayName = "RestrictedPage";

const AuthRestrictedPage = connectedEnsureAuth(RestrictedPage);

export default AuthRestrictedPage;

Полный консольный журнал ошибок

Консольный журнал при полном рендеринге.enter image description here

При удалении setState также запускается следующая строка: Warning: AuthBarrier: Error boundaries should implement getDerivedStateFromError(). In that method, return a state update to display an error message or fallback UI.

Соответствующие модули

  • «реагировать»: «^ 16.7.0»,
  • «реагировать-избыточно»: «^ 6.0.0»,
  • «реагировать-маршрутизатор»: «^ 4.3.1",
  • " подключен-реагирует-маршрутизатор ":" ^ 6.2.2 ",

1 Ответ

0 голосов
/ 18 февраля 2019

Границы ошибок были введены для одной-единственной цели: чтобы приложение не разрывалось при возникновении ошибки, верно?

Из документов:

КлассКомпонент становится границей ошибок, если он определяет (или оба) методы жизненного цикла static getDerivedStateFromError() или componentDidCatch().Используйте static getDerivedStateFromError() для визуализации резервного интерфейса после возникновения ошибки.Используйте componentDidCatch() для регистрации информации об ошибках.

Итак, идея проста:
getDerivedStateFromError - статическая функция, которая возвращает обновление состояния.

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

Если при попытке отобразить сообщение об ошибке граница не удастся, ошибка будет распространяться до ближайшей границы ошибки над ним.

В вашем примере, вы не используете getDerivedStateFromError, скорее componentDidCatch.В этой функции вы, возможно, отправили пользователя на другую страницу (это ваш способ решения этой ошибки ).Но если вы не установили состояние вручную (что должно было быть сделано с помощью getDerivedStateFromError), невозможно сказать, что ваша граница ошибки "справилась с этой ошибкой, она не должна идти выше ".

И мы знаем, что происходит, когда ошибка распространяется, и с ней некому разобраться:

Начиная с React 16, ошибки, которые не были обнаружены какой-либо границей ошибок, приведут кпри размонтировании всего дерева компонентов React.

Вот почему ваш «главный экран просто белый».

Надеюсь, это поможет. Документы об ошибке Граница

...