You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中跟踪Discord新窗口位置,遇错误URL自动关闭窗口

在React中跟踪新窗口位置并自动关闭指定URL窗口

问题原因

你之前用setInterval没生效,核心原因是跨域限制:当新窗口跳转到Discord的错误页面时,你的父页面(React应用)和新窗口属于不同域名,直接访问newWindow.location.href会触发浏览器的跨域安全报错,导致定时器内的代码中断执行,无法完成URL判断和窗口关闭操作。

解决方案

方案一:配置OAuth Redirect URI(推荐,可靠)

Discord OAuth支持通过redirect_uri参数指定授权完成后的跳转页面,你可以将跳转页设置为自己的前端页面,通过页面间通信实现窗口关闭:

  1. 修改窗口打开代码,添加redirect_uri参数(需先在Discord开发者后台配置该地址为合法回调地址):
const newWindow = window.open(
  `https://discord.com/oauth2/authorize?client_id=${clientId}&scope=bot&permissions=962311146056&guild_id=${guildId}&redirect_uri=${encodeURIComponent('https://你的域名.com/oauth-callback')}`,
  "_blank",
  "width=900,height=800"
);
  1. 创建OAuth回调页面(React组件),判断错误参数并通知父窗口:
// OAuthCallback.jsx
import { useEffect } from 'react';

export default function OAuthCallback() {
  useEffect(() => {
    const searchParams = new URLSearchParams(window.location.search);
    const error = searchParams.get('error');

    // 检测到授权拒绝错误,通知父窗口并关闭自身
    if (error === 'access_denied') {
      window.opener.postMessage({ type: 'CLOSE_OAUTH_WINDOW' }, '*');
      window.close();
    }
  }, []);

  return <div>处理授权中...</div>;
}
  1. 在父组件中监听消息事件,收到通知后关闭窗口:
import { useEffect, useState } from 'react';

export default function YourComponent() {
  const [newWindow, setNewWindow] = useState(null);

  const openAuthWindow = () => {
    const win = window.open(
      `https://discord.com/oauth2/authorize?client_id=${clientId}&scope=bot&permissions=962311146056&guild_id=${guildId}&redirect_uri=${encodeURIComponent('https://你的域名.com/oauth-callback')}`,
      "_blank",
      "width=900,height=800"
    );
    setNewWindow(win);
  };

  useEffect(() => {
    const handleMessage = (event) => {
      if (event.data.type === 'CLOSE_OAUTH_WINDOW' && newWindow) {
        newWindow.close();
      }
    };

    window.addEventListener('message', handleMessage);

    return () => {
      window.removeEventListener('message', handleMessage);
    };
  }, [newWindow]);

  return <button onClick={openAuthWindow}>打开授权窗口</button>;
}

方案二:跨域兼容的定时器监测(不推荐,不可靠)

如果无法配置回调地址,可通过捕获跨域错误的方式,尝试监测窗口状态:

import { useEffect } from 'react';

export default function YourComponent() {
  const errorUrl = "https://discord.com/oauth2/error?error=access_denied";
  let intervalId;

  const openAuthWindow = () => {
    const newWindow = window.open(
      `https://discord.com/oauth2/authorize?client_id=${clientId}&scope=bot&permissions=962311146056&guild_id=${guildId}`,
      "_blank",
      "width=900,height=800"
    );

    if (newWindow) {
      intervalId = setInterval(() => {
        try {
          // 尝试访问窗口URL,成功则判断是否为错误页面
          if (newWindow.location.href === errorUrl) {
            newWindow.close();
            clearInterval(intervalId);
          }
        } catch (e) {
          // 跨域错误时,检查窗口是否已关闭,关闭则清理定时器
          if (newWindow.closed) {
            clearInterval(intervalId);
          }
        }
      }, 1000);

      // 窗口关闭时自动清理定时器
      newWindow.addEventListener('beforeunload', () => {
        clearInterval(intervalId);
      });
    }
  };

  // 组件卸载时清理定时器
  useEffect(() => {
    return () => {
      if (intervalId) clearInterval(intervalId);
    };
  }, []);

  return <button onClick={openAuthWindow}>打开授权窗口</button>;
}

注意:方案二的可靠性较低,因为浏览器跨域策略可能会限制对第三方窗口的任何访问,部分场景下可能无法正常触发判断。

内容的提问来源于stack exchange,提问作者d3m0l15h

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 17:38:12