how to load the firebase data before component is rendered by lazy loading

22 Views Asked by At

The problem I have is that the moment the InfoAccount component starts loading and the fallback is displayed, this load is faster than the data I’m querying in firebase, which causes InfoAccount to load and after a short time the data I require is finished.

import { lazy, Suspense } from 'react'
import { CircularProgress } from '@mui/material'
import { SETTINGS_STRING } from '../constants/settingsConstans'
import { useSettings } from '../context/SettingsContext'

const InfoAccount = lazy(() => import('../components/InfoAccount'))
const ConfigEmail = lazy(() => import('../components/ConfigEmail'))
const ConfigPassword = lazy(() => import('../components/ConfigPassword'))

function SettingsMain () {
  const { 
    viewInfoAccount, 
    viewEmailInfo, 
    viewPasswordInfo, 
    viewConfig: { cfgEmail, cfgInfo, cfgPass } 
  } = useSettings()
  const { INFO_ACCOUNT, INFO_EMAIL, INFO_PASS, TITLE } = SETTINGS_STRING
  return (
    <>
      <h2>{TITLE}</h2>
      <section className='settings-block'>
        <aside className='aside-settings'>
          <ul>
            <li onClick={viewInfoAccount}>{INFO_ACCOUNT}</li>
            <li onClick={viewEmailInfo}>{INFO_EMAIL}</li>
            <li onClick={viewPasswordInfo}>{INFO_PASS}</li>
          </ul>
        </aside>
        <section className='frame-settings'>
          <Suspense fallback={<CircularProgress />}>
            {cfgInfo ? <InfoAccount /> : <></>}
            {cfgEmail ? <ConfigEmail /> : <></>}
            {cfgPass ? <ConfigPassword /> : <></>}
          </Suspense>
        </section>
      </section>
    </>
  )
}

export default SettingsMain

When I click on InfoAccount I start to read the data and in turn I establish the state to show InfoAccount, that’s where the Fallback CircularProgress is triggered

import { useSettings } from '../context/SettingsContext'

function InfoAccount () {
  const { info } = useSettings()
  const { accountCreationDate, loginWithGoogle } = info
  return (
    <>
      <ul>
        <li>Fecha de registro: {accountCreationDate}</li>
        <li>Método de registro: {loginWithGoogle ? 'Cuenta de google' : 'Correo electrónico'}</li>
      </ul>
    </>
  )
}

export default InfoAccount

But it loads faster InfoAccount than the data it will show, leaving something like this:

'Fecha de registro: '
'Método de registro: Correo Electrónico'

After a few moments is shown this:

'Fecha de registro: 28/11/2023' <----------
'Método de registro: Correo Electrónico'

This is SettingsContext:

import { createContext, useContext, useState } from 'react'
import { useAuth } from '../context/AuthContext'
import { db } from '../../configFirebase.js'
import { doc, getDoc } from 'firebase/firestore'

const SettingsContext = createContext()

export const useSettings = () => {
  const context = useContext(SettingsContext)
  return context
}

export function SettingsProvider ({ children }) {
  const { user: { uid } } = useAuth()

  const [viewConfig, setViewConfig] = useState({
    cfgInfo: false,
    cfgEmail: false,
    cfgPass: false
  })

  const [info, setInfo] = useState({
    accountCreationDate: '',
    loginWithGoogle: false
  })

  const readRegisterInfo = async () => {           // here I read data of interest
    const docRef = doc(db, 'users', uid)
    const docSnap = await getDoc(docRef)
    const { accountCreationDate, loginWithGoogle } = docSnap.data()
    setInfo({ accountCreationDate, loginWithGoogle })
  }

  const viewInfoAccount = () => {
    readRegisterInfo()  // run the read and then show the component
    setViewConfig({ cfgEmail: false, cfgPass: false, cfgInfo: true })
  }

  const viewEmailInfo = () => {
    setViewConfig({ cfgInfo: false, cfgPass: false, cfgEmail: true })
  }

  const viewPasswordInfo = () => {
    setViewConfig({ cfgInfo: false, cfgEmail: false, cfgPass: true })
  }

  return (
    <SettingsContext.Provider
      value={{
        info,
        setInfo,
        readRegisterInfo,
        viewInfoAccount,
        viewEmailInfo,
        viewPasswordInfo,
        viewConfig
      }}
    >
      {children}
    </SettingsContext.Provider>
  )
}

0

There are 0 best solutions below