Почему сначала выполняется рендеринг этого компонента React? - PullRequest
1 голос
/ 27 мая 2020

Я мог бы использовать ваш ответ для быстрого вопроса о загрузке компонентов.

Цель

Вернуть компонент <Login />, если пользователь не вошел в систему, и приложение, если они

Ожидаемое поведение

Когда пользователь вошел в систему, он видит приложение.

Наблюдаемое поведение

Компонент <Login /> мерцает (отображает ) на мгновение, затем пользователь видит приложение. Моя цель - устранить это мерцание!

Примеры кода

Индекс. js

export default function Index() {

  let [isLoading, setIsLoading] = useState(true)

  const router = useRouter()

  // User object comes in from an Auth Context Provider
  const { user } = useContext(AuthContext)
  const { email } = user

  useEffect(() => {
    if (user) {
      setIsLoading(false)
    }
  }, [])

  // Returns the App if logged in, login screen if not
  const getLoggedIn = () => {
    if (user.loggedIn) {
      return (
        <>
          // App goes here
        </>
      )
    } else {
      return <Login />
    }
  }

  return (
    <Box className="App">
      { isLoading
      ? <div className={classes.root}>
          <LinearProgress />
        </div>
      : getLoggedIn()
      }
    </Box>
  )
}

Контекст аутентификации

Примечание. Я использую Firebase для аутентификации.

 // Listens to auth state changes when App mounts
  useEffect(() => {
    // Calls setUser state update method on callback
    const unsubscribe = onAuthStateChange(setUser)
    return () => {
      unsubscribe()
    }
  }, [])
  
  // Brings data from auth to Auth Context user state via callback
  const onAuthStateChange = callback => {
    return auth.onAuthStateChanged(async user => {
      if (user) {
        const userFirestoreDoc = await firestore.collection('users').doc(user.uid).get()
        const buildUser = await callback({ 
          loggedIn: true, 
          email: user.email, 
          currentUid: user.uid, 
          userDoc: userFirestoreDoc.data()
        })
      } else {
        callback({ loggedIn: false })
      }
    })
  }

Стек

"next": "^8.1.0",
"react": "^16.8.6",
"react-dom": "^16.8.6"

Большое спасибо за внимание.

Ответы [ 2 ]

1 голос
/ 28 мая 2020

У меня была именно эта проблема, и я решил ее, сохранив пользователя в локальном хранилище

, затем при запуске приложения сделайте это:

const [user, setUser] = useState(JSON.parse(localStorage.getItem('authUser')))

и это ' Я воспользуюсь данными из localstorage, и вы не увидите мерцания

(это потому, что onauthstate запускается дольше)

0 голосов
/ 28 мая 2020

Итак, я придумал что-то вроде «хакерского» способа обойти это. Необходимо установить значение логического значения, от которого зависит начальная загрузка приложения ...

const getLoggedIn = () => {
    // Right here
    if (user.loggedIn) {
      return (
        <>
          // App goes here
        </>
      )
    } else {
      return <Login />
    }

... до выполнения любых асинхронных вызовов в AuthContext. Вот так:

const onAuthStateChange = callback => {
    return auth.onAuthStateChanged(async user => {
      if (user) {
        // sets loggedIn to true to prevent flickering to login screen on load
        callback({ loggedIn: true })
        const userFirestoreDoc = await firestore.collection('users').doc(user.uid).get()
        const buildUser = await callback({ 
          loggedIn: true,
          email: user.email, 
          currentUid: user.uid, 
          userDoc: userFirestoreDoc.data()
        })
      } else {
        callback({ loggedIn: false })
      }
    })
  }

Надеюсь, это кому-то поможет.

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