From fcefac9dbef04611b464173fa1862860d1badf4b Mon Sep 17 00:00:00 2001 From: t0ng7u Date: Wed, 25 Jun 2025 22:46:11 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(auth):=20prevent=20initial?= =?UTF-8?q?=20render=20flicker=20&=20clean=20up=20state=20usage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • LoginForm / RegisterForm now initialise `status` directly from localStorage, avoiding a post-mount state update that caused a UI flash between OAuth options and email/username forms. • Move Turnstile configuration into a dedicated effect that depends on `status`, ensuring setState is not called during rendering. • Remove unused `setStatus` setter to resolve ESLint “declared but never read” warnings. • Minor refactors: reorder hooks, de-duplicate navigate/context variables and streamline state destructuring for improved readability. --- web/src/components/auth/LoginForm.js | 34 +++++++++++++------------ web/src/components/auth/RegisterForm.js | 31 +++++++++++----------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/web/src/components/auth/LoginForm.js b/web/src/components/auth/LoginForm.js index ba254cdd..9b67a806 100644 --- a/web/src/components/auth/LoginForm.js +++ b/web/src/components/auth/LoginForm.js @@ -34,20 +34,20 @@ import LinuxDoIcon from '../common/logo/LinuxDoIcon.js'; import { useTranslation } from 'react-i18next'; const LoginForm = () => { + let navigate = useNavigate(); + const { t } = useTranslation(); const [inputs, setInputs] = useState({ username: '', password: '', wechat_verification_code: '', }); - const [searchParams, setSearchParams] = useSearchParams(); - const [submitted, setSubmitted] = useState(false); const { username, password } = inputs; - const [userState, userDispatch] = useContext(UserContext); + const [searchParams] = useSearchParams(); + const [setSubmitted] = useState(false); + const [userDispatch] = useContext(UserContext); const [turnstileEnabled, setTurnstileEnabled] = useState(false); const [turnstileSiteKey, setTurnstileSiteKey] = useState(''); const [turnstileToken, setTurnstileToken] = useState(''); - let navigate = useNavigate(); - const [status, setStatus] = useState({}); const [showWeChatLoginModal, setShowWeChatLoginModal] = useState(false); const [showEmailLogin, setShowEmailLogin] = useState(false); const [wechatLoading, setWechatLoading] = useState(false); @@ -59,7 +59,6 @@ const LoginForm = () => { const [resetPasswordLoading, setResetPasswordLoading] = useState(false); const [otherLoginOptionsLoading, setOtherLoginOptionsLoading] = useState(false); const [wechatCodeSubmitLoading, setWechatCodeSubmitLoading] = useState(false); - const { t } = useTranslation(); const logo = getLogo(); const systemName = getSystemName(); @@ -69,20 +68,23 @@ const LoginForm = () => { localStorage.setItem('aff', affCode); } + const [status] = useState(() => { + const savedStatus = localStorage.getItem('status'); + return savedStatus ? JSON.parse(savedStatus) : {}; + }); + + useEffect(() => { + if (status.turnstile_check) { + setTurnstileEnabled(true); + setTurnstileSiteKey(status.turnstile_site_key); + } + }, [status]); + useEffect(() => { if (searchParams.get('expired')) { showError(t('未登录或登录已过期,请重新登录')); } - let status = localStorage.getItem('status'); - if (status) { - status = JSON.parse(status); - setStatus(status); - if (status.turnstile_check) { - setTurnstileEnabled(true); - setTurnstileSiteKey(status.turnstile_site_key); - } - } - }, []); + }, [searchParams, t]); const onWeChatLoginClicked = () => { setWechatLoading(true); diff --git a/web/src/components/auth/RegisterForm.js b/web/src/components/auth/RegisterForm.js index 4009c1fa..d1e041ce 100644 --- a/web/src/components/auth/RegisterForm.js +++ b/web/src/components/auth/RegisterForm.js @@ -35,6 +35,7 @@ import { UserContext } from '../../context/User/index.js'; import { useTranslation } from 'react-i18next'; const RegisterForm = () => { + let navigate = useNavigate(); const { t } = useTranslation(); const [inputs, setInputs] = useState({ username: '', @@ -45,15 +46,12 @@ const RegisterForm = () => { wechat_verification_code: '', }); const { username, password, password2 } = inputs; - const [showEmailVerification, setShowEmailVerification] = useState(false); - const [userState, userDispatch] = useContext(UserContext); + const [userDispatch] = useContext(UserContext); const [turnstileEnabled, setTurnstileEnabled] = useState(false); const [turnstileSiteKey, setTurnstileSiteKey] = useState(''); const [turnstileToken, setTurnstileToken] = useState(''); - const [loading, setLoading] = useState(false); const [showWeChatLoginModal, setShowWeChatLoginModal] = useState(false); const [showEmailRegister, setShowEmailRegister] = useState(false); - const [status, setStatus] = useState({}); const [wechatLoading, setWechatLoading] = useState(false); const [githubLoading, setGithubLoading] = useState(false); const [oidcLoading, setOidcLoading] = useState(false); @@ -63,7 +61,6 @@ const RegisterForm = () => { const [verificationCodeLoading, setVerificationCodeLoading] = useState(false); const [otherRegisterOptionsLoading, setOtherRegisterOptionsLoading] = useState(false); const [wechatCodeSubmitLoading, setWechatCodeSubmitLoading] = useState(false); - let navigate = useNavigate(); const logo = getLogo(); const systemName = getSystemName(); @@ -73,18 +70,22 @@ const RegisterForm = () => { localStorage.setItem('aff', affCode); } + const [status] = useState(() => { + const savedStatus = localStorage.getItem('status'); + return savedStatus ? JSON.parse(savedStatus) : {}; + }); + + const [showEmailVerification, setShowEmailVerification] = useState(() => { + return status.email_verification ?? false; + }); + useEffect(() => { - let status = localStorage.getItem('status'); - if (status) { - status = JSON.parse(status); - setStatus(status); - setShowEmailVerification(status.email_verification); - if (status.turnstile_check) { - setTurnstileEnabled(true); - setTurnstileSiteKey(status.turnstile_site_key); - } + setShowEmailVerification(status.email_verification); + if (status.turnstile_check) { + setTurnstileEnabled(true); + setTurnstileSiteKey(status.turnstile_site_key); } - }, []); + }, [status]); const onWeChatLoginClicked = () => { setWechatLoading(true);