Слушатели аутентификации при рефакторинге для перехватчиков React - PullRequest
0 голосов
/ 05 апреля 2019

У меня небольшие проблемы с выяснением того, как изменить компонент обработки аутентификации при рефакторинге с класса React на перехватчики React.

Вот соответствующий код в моем классе :

  state = {
    user: null
  }

  componentDidMount() {

    authGetUser(user => {
      if (user !== this.state.user) {
        this.setState({user})
      }
    })
  }

  componentWillUnmount() {

    authUnsubscribe()
  }

  handleAuthClick = () => {

    if (this.state.user) {
      authSignOut()
    } else {
      authSignIn()
    }
  }

И вот он с крючками :

  const [user, setUser] = useState<firebase.User | null>(null)

  useEffect(() => {
    return authUnsubscribe() // runs on mount and unmount only
  }, [])

  useEffect(() => {
    authGetUser(usr => setUser(usr))
  }, [])

  const handleAuthClick = () => {

    if (user) {
      authSignOut()
    } else {
      authSignIn()
    }
  }

Кроме того, вот мои другие соответствующие методы:

const authGetUser = (callback: (user: firebase.User | null) => void) => {

  initFirebase()
  authUnsubscribe()
  userUnsubscribe = firebaseAuth.onAuthStateChanged(callback)
}

export const authUnsubscribe = () => {

  if (userUnsubscribe) {
    userUnsubscribe()
  }
}

const authSignIn = () => {

  googleAuth.signIn().then((googleUser: any) => {

    var credential = firebase.auth.GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token)

    firebaseAuth.signInAndRetrieveDataWithCredential(credential)
  })
}

const authSignOut = () => {

  googleAuth
  .signOut()
  .then(firebaseAuth.signOut())
}

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

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

, которое говорит о том, что очистка не выполняется должным образом.

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

Есть идеи?

Ответы [ 2 ]

0 голосов
/ 07 апреля 2019

Как правило, это происходит, когда у нас есть асинхронные запросы, и компонент ранее был отключен, что приводит к утечке памяти.Очевидно, что этого не происходит в компонентах на основе классов, потому что у нас есть componentDidMount() и componentWillUnmount() хуки, поэтому мы более уверены, чем useEffect(), что мы манипулировали состоянием, поэтому я думаю, что вам нужно определить причинуприложение размонтируется, и есть решение.

Вы должны использовать один useEffect() вместо двух, как это:

useEffect(() => {
  authGetUser(usr => setUser(usr))
  return authUnsubscribe() // runs on mount and unmount only
}, [])
0 голосов
/ 05 апреля 2019

Разве это не работает для вас? Вы можете использовать один useEffect().

React Hooks API DOCs

useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      // Clean up the subscription
      setUser(null); // <--- TRY DOING SOMETHING LIKE THIS
      subscription.unsubscribe();
    };
  },
  [],
); 

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


Если вы хотите запустить эффект и очистить его только один раз (при монтировании и unmount), вы можете передать пустой массив ([]) в качестве второго аргумента. это говорит React, что ваш эффект не зависит от значений реквизита или состояние, так что никогда не нужно повторно запускать. Это не обрабатывается как особый case - это следует непосредственно из того, как массив зависимостей всегда работы.

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