typescript react useEffect调用两次

au9on6nz  于 2023-03-04  发布在  TypeScript
关注(0)|答案(2)|浏览(254)

我正在开发一个api与express.js和认证系统,我使用从jwt库和刷新和访问令牌。一切工作时,我测试我的代码与jest和supertest和测试它与 Postman 。
在前端,我使用react,并将刷新令牌保存在cookie(仅httpOnly)中,使用redux将用户数据(如访问令牌、刷新令牌和用户名)保存在内存中,一切正常(路由保护等)。
当用户离开程序时,存储器被清除(保存在redux中的用户信息将被删除),当程序的用户返回登录页面时,这是正常的。
但是我在cookie中有刷新令牌,并且我用withCredentials=true的axios方法向**/tokens**API发送post请求,用于生成新的访问和刷新令牌,一切正常,并返回新令牌和用户数据,并且用户没有重定向到验证页面。

    • 问题是**

我使用react版本18.2.0,并且我知道当在开发模式下的useEffect中调用两次useEffect时,没有问题。我向/tokens api发送post请求,以在useEffect中生成新的访问和刷新令牌。根据前面的语句,在开发模式下发送了两次此请求。
我在api中的逻辑,使用与cookie一起发送的刷新令牌搜索用户,如果找到用户,则生成新令牌。

    • 但我注意到在两次调用中,第一次api调用(/tokens)找到用户,但第二次调用无法找到用户并返回未定义**,有时两次调用都成功,这很奇怪。
    • 这是我的密码**

React代码:

useEffect(() => {

    if (user === undefined) {
      axios.post('/tokens').then((result: any) => {

        dispatch(addUser(result.data.user));

      }).catch((error: any) => {
        dispatch(addUser(undefined))
      })
    }
  }, []);

后端代码:

tokens = async (req: Request, res: Response, next: NextFunction): Promise<Response> => {

      
        const refreshToken = req.headers.cookie?.split('=')[1];

     
        const user: any[] = await this._userRepository.find({
            fields: [
                {
                    field: {
                        username: req.user.username,
                        email: req.user.email,
                        id: req.user.id,
                        refresh_token: refreshToken
                    },
                    op: 'AND'
                }
            ]
        });

   
        // in here sometimes find user and sometimes cannot find user with same data
        if (user[0] !== undefined) {

        
            const newAccessToken: string = generateJwt('access_token', user[0], '1m');

          
            const newRefreshToken: string = generateJwt('refresh_token', user[0], '10d');

       
            await this._userRepository.update({
                refresh_token: newRefreshToken,
            }, {
                fields: [
                    {
                        field: {
                            id: req.user.id,
                            username: req.user.username,
                            email: req.user.email,
                            refresh_token: refreshToken
                        },
                        op: 'AND'
                    }
                ]
            });

         
            const data: Record<string, any> = {
                status: true,
                message: 'New tokens generated successfully',
                user: {
                    access_token: newAccessToken,
                    refresh_token: newRefreshToken,
                }
            }

           

           
            return res.json(data)
        }

        // send error
        throw new BaseError('Unauthorized', 401);
    }
wh6knrhe

wh6knrhe1#

这将发生在react的开发模式下。当一个组件最初呈现时,useEffect运行两次。当您在生产模式下提供react构建时,不会出现此问题。有一个解决方案可以停止两次调用useEffect,您必须从根文件中删除React.Strict,但不推荐使用此方法。

s4n0splo

s4n0splo2#

如果我们将前面的代码作为基础,我会看到useEffect为它提供了匿名函数,但我注意到它每次都会执行,也许这个函数只执行一次是个好主意,这是通过为第二个参数为useEffect函数的数组提供一个或多个变量来实现的,我可以理解,只要user变量被修改,您就希望它被执行,所以如果它被修改并且仍然未定义,则继续通过axios进行调用,如果没有,则什么也不做。

useEffect(() => {

if (user === undefined) {
  axios.post('/tokens').then((result: any) => {

    dispatch(addUser(result.data.user));

  }).catch((error: any) => {
    dispatch(addUser(undefined))
  })
}
}, [user]);

相关问题