React中Discord Activity加载时Setup函数执行两次致认证异常求助
Discord Activity Setup函数执行两次导致认证错误的解决方案
我希望Discord Activity加载时仅执行一次Setup函数,但代码中该函数执行了两次并引发错误(控制台错误截图:
)。其他功能正常,仅认证环节出现问题。
问题代码
function App() { const [auth, setAuth] = useState<authType>(null); async function setupDiscordSdk() { const CLIENT_ID = "my client id"; const discordSdk = new DiscordSDK(CLIENT_ID, { disableConsoleLogOverride: true }); await discordSdk.ready(); console.warn('DISCORD SDK READY!') // 该日志打印两次 // 向Discord客户端授权 const { code } = await discordSdk.commands.authorize({ client_id: CLIENT_ID, response_type: "code", state: "", prompt: "none", scope: [ "identify", ], }); // 从活动服务器获取access_token const response = await fetch("/api/token", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ code, }), }); const { access_token, publicProfile, authkey } = await response.json(); localStorage.setItem('bread:authkey', authkey); // 使用access_token向Discord客户端认证 let auth = (await discordSdk.commands.authenticate({ access_token, }) as authTypeNOTNULL); auth.publicProfile = publicProfile as boolean; auth.user.avatarURL = (auth.user.avatar ? `https://cdn.discordapp.com/avatars/${auth.user.id}/${auth.user.avatar}.png?size=256` : `https://cdn.discordapp.com/embed/avatars/${(BigInt(auth.user.id) >> 22n) % 6n}.png`); auth.discordSdk = discordSdk; setAuth(auth); console.warn('AUTHED SUCCESSFULLY.'); }; async function openLink(url: string) { console.warn('Trying to open URL', url); console.log(auth) if (!auth) return console.error('Not authed'); return await auth.discordSdk.commands.openExternalLink({ url }); }; useEffect(() => console.log(auth), [auth]); useEffect(() => { setupDiscordSdk().catch(console.error); }, []) return ( <> ... </> ) } export default App;
解决方案
1. 理解触发原因
React 18+的开发模式下,StrictMode会强制重复执行空依赖的useEffect、组件构造函数等,用于检测潜在bug,生产环境不会有此行为。这是setupDiscordSdk执行两次的最常见原因。
2. 添加执行锁避免重复调用
使用useRef标记是否已执行过初始化,不会触发组件重渲染,是最简洁的方案:
function App() { const [auth, setAuth] = useState<authType>(null); const isSetupCompleted = useRef(false); // 新增ref标记 async function setupDiscordSdk() { if (isSetupCompleted.current) return; // 已执行则直接返回 isSetupCompleted.current = true; // 标记为已执行 // 原有setup代码... }; // 其他函数... useEffect(() => { setupDiscordSdk().catch(console.error); }, []) // ... }
3. 临时关闭StrictMode(仅开发调试用)
找到项目入口文件(如index.tsx),移除<StrictMode>组件的包裹:
// 原代码 root.render( <StrictMode> <App /> </StrictMode> ); // 修改后 root.render( <App /> );
注意:此方案仅用于开发时验证问题,不建议长期关闭StrictMode,它能帮助提前发现很多潜在问题。
4. 检查组件挂载情况
确认App组件是否在应用中被多次渲染(比如路由配置错误、父组件重复渲染导致子组件重复挂载),确保组件仅挂载一次。
5. 生产环境验证
打包生产版本后,React StrictMode的双重执行逻辑会被移除,此时setupDiscordSdk会自然只执行一次,可以直接验证问题是否解决。
内容的提问来源于stack exchange,提问作者Kodeur_Kubik
相关产品推荐
相关产品推荐

