I'm trying to fix a design issue, where in a certain case, the classes declared in a <div className="XXXX"></div>
are not attached the the div in the dom.
This happen when i directly hit the endpoint /dashboard
of my Next.JS website but not when I use router.push('/dashboard')
of next/router (when i'm on /
)
My project is organised like this:
├── components
│ ├── Dashboard
│ │ ├── Dashboard.jsx
│ │ └── UnAuthorized.jsx
│ ├── Emoji.jsx
│ ├── Landing
│ │ ├── AskRecoveryModal.jsx
│ │ ├── index.jsx
│ │ ├── RecoveryModal.jsx
│ │ ├── SignIn.jsx
│ │ └── SignUp.jsx
│ └── Layout
│ ├── Footer.jsx
│ └── index.jsx
├── package.json
├── package-lock.json
├── pages
│ ├── api
│ │ └── hello.js
│ ├── _app.js
│ ├── dashboard.js
│ └── index.js
├── postcss.config.js
├── public
│ ├── cryptopolitain-logo.png
│ ├── favicon.ico
│ └── vercel.svg
├── README.md
├── styles
│ ├── globals.css
│ └── Home.module.css
└── tailwind.config.js
The index.js
:
import Layout from "../components/Layout"
import Landing from "../components/Landing/"
export default function Home() {
return (
<Layout>
<Landing />
</Layout>
)
}
The SignIn.jsx
(which is imported in ):
import { useRouter } from 'next/router'
import { useEffect, useRef, useState } from 'react'
import { Button, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, TextField } from '@material-ui/core'
import { Spinner } from 'bumbag'
import { useIdentityContext } from 'react-netlify-identity'
import AskRecoveryModal from './AskRecoveryModal'
export default function SignUpButton () {
const formRef = useRef()
const router = useRouter()
const { loginUser } = useIdentityContext()
useEffect(() => {
})
const [open, setOpen] = useState(false)
const handleOpen = () => setOpen(true)
const handleClose = () => {
setOpen(false)
document.getElementById("connection-form").reset()
setMsg("")
}
const initialState = {
errorPassword: false,
errorPasswordtext: "",
errorEmail: false,
errorEmailText: ""
}
const [state, setState] = useState(initialState)
const [waitForResponse, setWaitForResponse] = useState(false)
const [msg, setMsg] = useState("")
const signIn = () => {
setWaitForResponse(true)
const email = formRef.current.email.value
const password = formRef.current.password.value
loginUser(email, password, true)
.then(user => {
setWaitForResponse(false)
console.log('Success! Logged in', user)
router.push('/dashboard')
})
.catch(err => {
setWaitForResponse(false)
console.error(err)
setMsg("Combinaison incorrecte, as-tu vérifié ton email ?")
})
}
const handleKeyDown = (e) => {
if (e.key === 'Enter') {
signIn()
}
}
const [openRecoveryModal, setOpenRecoveryModal] = useState(false)
const closeRecoveryModal = () => setOpenRecoveryModal(false)
const askRecovery = () => {
setOpen(false)
setOpenRecoveryModal(true)
}
return (
<div>
<Button variant="contained" color="primary" size="large" onClick={() => handleOpen()}>Connexion</Button>
<Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
<DialogTitle id="form-dialog-title"><div className="text-2xl">Se connecter</div></DialogTitle>
<DialogContent>
<div className="md:w-80">
<DialogContentText style={{ fontSize: `0.9rem` }}>
Connectez-vous pour acceder au dashboard
{msg !== "" && <div className="text-red-600"><br />{msg}</div>}
</DialogContentText>
</div>
<form ref={formRef} id="connection-form">
<div className="mt-3">
<TextField
autoFocus
error={state.errorEmail}
helperText={state.errorEmailText}
name="email"
label="Email"
type="email"
fullWidth
autoComplete="email"
onKeyDown={(e) => handleKeyDown(e)}
/></div>
<div className="mt-3">
<TextField
error={state.errorPassword}
helperText={state.errorPasswordText}
name="password"
label="Mot de passe"
type="password"
fullWidth
autoComplete="password"
onKeyDown={(e) => handleKeyDown(e)}
/>
</div>
</form>
{msg !== "" && <button onClick={() => askRecovery()} className="text-xs mt-3 text-red-700 hover:text-red-500">Mot de passe oublié ?</button>}
</DialogContent>
<DialogActions>
<Button onClick={() => handleClose()} >
Annuler
</Button>
<Button onClick={() => signIn()} color="primary" variant="contained">
{waitForResponse ? <Spinner /> : `Se connecter`}
</Button>
</DialogActions>
</Dialog>
<AskRecoveryModal open={openRecoveryModal} handleClose={() => closeRecoveryModal()} />
</div>
)
}
The Dashboard.jsx
component is:
import Layout from '../Layout'
import Emoji from '../Emoji'
import { useIdentityContext } from 'react-netlify-identity'
import { useRouter } from 'next/router'
import { Button } from '@material-ui/core'
export default function Dashboard() {
const { logoutUser } = useIdentityContext();
const router = useRouter()
const logout = () => {
logoutUser()
router.push('/')
}
return (
<div className="w-full h-full flex flex-col justify-center items-center"> {* THE ISSUE IS HERE *}
<div className="mb-12 text-xl">Dashboard en construction... <Emoji symbol="??" label="construction"/></div>
<Button variant="outlined" color="primary" size="large" onClick={() => logout()}>Se déconnecter</Button>
</div>
)
}
and is called by pages/dashboard.js
which is:
import { useIdentityContext } from 'react-netlify-identity'
import Dashboard from '../components/Dashboard/Dashboard'
import UnAuthorized from '../components/Dashboard/UnAuthorized'
import Layout from '../components/Layout'
export default function DashboardRoute () {
const identity = useIdentityContext()
return (
<Layout>
{identity.user ? <Dashboard /> : <UnAuthorized />}
</Layout>
)
}
I tried to go on the Profiler section of the React Dev Tools, but there is absolutely 0 difference between the render tree of the two cases.
But in fact when I go directly to /dashboard
the div on the real DOM don't have his classes. (but his child <div className="mb-12 text-xl">
is good.
And when I use router.push('/dashboard')
from /
the div on the real DOM have his classes.
I hope to have been clear, I can give more information if needed.
Thanks you !