Explorar o código

🐛 fix(auth): prevent initial render flicker & clean up state usage

• 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.
t0ng7u hai 8 meses
pai
achega
fcefac9dbe
Modificáronse 2 ficheiros con 34 adicións e 31 borrados
  1. 18 16
      web/src/components/auth/LoginForm.js
  2. 16 15
      web/src/components/auth/RegisterForm.js

+ 18 - 16
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);

+ 16 - 15
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);