javascript - 为什么我的纯功能组件呈现不同?
问题描述
我正在尝试解决一个设计问题,在某种情况下,在 a 中声明的类<div className="XXXX"></div>
未附加到 dom 中的 div。
当我直接点击/dashboard
我的 Next.JS 网站的端点时会发生这种情况,但当我使用router.push('/dashboard')
next/router 时不会发生这种情况(当我打开时/
)
我的项目是这样组织的:
├── 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
index.js
:_
import Layout from "../components/Layout"
import Landing from "../components/Landing/"
export default function Home() {
return (
<Layout>
<Landing />
</Layout>
)
}
(在SignIn.jsx
中导入):
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>
)
}
Dashboard.jsx
组件是:
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>
)
}
并被称为pages/dashboard.js
:
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>
)
}
我试图继续 React Dev Tools 的 Profiler 部分,但两种情况的渲染树之间绝对有 0 差异。
但实际上当我直接进入/dashboard
真正的 DOM 上的 div 时并没有他的类。(但他的孩子<div className="mb-12 text-xl">
很好。
而当我router.push('/dashboard')
从/
div 上使用真实的 DOM 时,就有了他的类。
我希望清楚,如果需要,我可以提供更多信息。
谢谢 !
解决方案
推荐阅读
- angular - NG8002:无法绑定到“ngModel”,因为它不是“输入”的已知属性。角 10
- python - 如何使用 Python 在 Lambda 中为 CloudFront 生成 SignedUrls?
- javascript - 在 JavaScript 中重写 Element 接口的构造函数
- javascript - 如何在 Leaflet 弹出窗口中添加链接?
- spring - 接收由 HTTP.POST 发布的对象
- python - TypeError,使用 Sci-Kit Learn Regression 进行机器学习
- react-native - 如何在本机反应中设置数组并从键中获取值
- spring-boot - Id 到实体的转换在 Spring Boot 2.2.8 及更高版本中不起作用
- junit5 - MockMvc POST 返回 400 - 期待 201
- java - 使用 DateTimeFormatter 正确调整时间