reactjs 不需要的useEffect调用与axios

7xzttuei  于 2023-04-20  发布在  React
关注(0)|答案(2)|浏览(127)

我正在使用React、Express和Axios创建一个带有令牌参数的验证页面
下面是页面脚本:

import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';
import { Typography } from '@mui/material';

const VerifyPage = () => {
    const { token } = useParams();
    const [verificationResult, setVerificationResult] = useState<any>(null);

    useEffect(() => {
        const verifyEmail = async () => {
            try {
                if (verificationResult) return;
                const res = await axios.get(`http://localhost:5000/api/auth/verify/${token}`);
                console.log(res.data.message);
                if (res && res.data) {
                    setVerificationResult(res.data.message);
                } else {
                    setVerificationResult('Something went wrong');
                    throw new Error('Something went wrong');
                }
                return;
            } catch (error: any) {
                setVerificationResult(error.message);
                return;
            }
        };

        verifyEmail();
    }, [token]);

    return (
        <div id='VerifyPage'>
            {verificationResult ? (
                <Typography variant='h1' align='center' sx={{ mt: 30, fontFamily: 'Noto Sans', color: 'white' }}>
                    <strong>{verificationResult}</strong>
                </Typography>
            ) : (
                <Typography variant='h1' align='center' sx={{ mt: 30, fontFamily: 'Noto Sans', color: 'white' }}>
                    <strong>Verifying...</strong>
                </Typography>
            )}
        </div>
    );
};

export default VerifyPage;

下面是API

const verifyEmail = async (verificationToken: string) => {
    try {
        const user = await User.findOne({ verificationToken });
        if (!user) {
            return 'Invalid token';
        }
        if (user.verified) {
            return 'Email already verified';
        }
        await User.updateOne({ verificationToken }, { verified: true });
        return 'Email verified';
    } catch (err) {
        console.log(err);
        return 'Server error';
    }
};

app.get('/api/auth/verify/:verificationToken', async (req: Request, res: Response) => {
    const { verificationToken } = req.params;
    const message = await verifyEmail(verificationToken);
    res.send({ message: message });
});

用户收到一封包含链接和令牌的电子邮件。当我打开验证页面时,useEffect向服务器发送多个axios请求。这导致始终显示“Email already verified”(因为它验证了它,然后尝试再次验证)。
我试过使用条件,比如
if (verificationResult) return;
或者甚至创建新的状态变量,
const [verified, setVerified] = useState<boolean>(false);

if (verified) return;
但什么都没变
为什么会这样?我做错了什么?:)

编辑1我尝试使用

if (verificationResult !== null) return;

但什么都没改变我也试着

console.log('UseEffect ran');
console.log(verificationResult);

每次运行时,它似乎都保持为null。我相信这是因为verifyEmail函数是异步的。似乎当状态为null时,useEffect会运行多次,直到它从服务器获得响应(最后2)。我如何修复这种不受控制的useEffect调用(也许让它等待直到它从服务器获得响应)?顺便说一句,谢谢你的帮助〈3

blmhpbnm

blmhpbnm1#

找到问题了!经过研究,我发现这种情况只发生在开发模式下。这是因为从React 18开始,useEffect被调用了两次,即使它有空的依赖数组。我通过从index.ts中删除****来修复这个问题<React.StrictMode>

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
   <React.StrictMode>
        <App />
   </React.StrictMode>
);

更多信息:React Hooks: useEffect() is called twice even if an empty array is used as an argument

mwg9r5ms

mwg9r5ms2#

你是正确的亚历克斯,这发生在我身上在我以前的项目.如果你检查以下链接:React docs - Strict Mode,你会看到它特别提到:

  • 您的组件将重新呈现额外的时间,以查找由不纯呈现引起的错误。
  • 您的组件将重新运行效果一段额外的时间,以查找由于缺少效果清理而导致的错误。
  • 将检查您的组件是否使用了已弃用的API。

最佳实践是添加一个标志,以便仅在组件完全呈现时才运行API调用:
1.用于更新布尔值的附加useEffect
1.检查布尔值以触发API调用

相关问题