React路由跳转后如何执行第三方JS函数以加载验证码
Got it, I’ve run into this exact issue before with third-party scripts in React single-page apps! The problem boils down to how SPAs work: when you refresh the page, the entire browser context reloads—including the third-party captcha script that initializes itself on page load. But when you navigate via React Router, only the component tree updates; the page doesn’t fully reload, so the captcha’s auto-initialization never triggers again.
Luckily, you already found the magic function: window.__challenger.callPageRequest(). We just need to make sure this runs every time your form component mounts or navigates into view. Here’s how to implement this in both function and class components:
Function Component (React Hooks)
Use useEffect paired with useLocation to detect when the route lands on your form page. We’ll also add a safety check to make sure the third-party script is loaded before calling the function:
import { useEffect, useRef } from 'react'; import { useLocation } from 'react-router-dom'; const FormWithCaptcha = () => { const location = useLocation(); const captchaContainerRef = useRef(null); const initCaptcha = () => { // Double-check the function exists to avoid errors if (window.__challenger?.callPageRequest) { window.__challenger.callPageRequest(); } else { // If the script is still loading, retry after a short delay setTimeout(initCaptcha, 150); } }; useEffect(() => { // Wait until the captcha container is rendered (optional but safe) if (captchaContainerRef.current) { initCaptcha(); } // Cleanup if needed (some captchas require destruction on unmount) return () => { // Add any cleanup logic here if the third-party script provides it }; }, [location.pathname]); // Trigger on route change to this page return ( <form> {/* Your form fields */} <div ref={captchaContainerRef} className="captcha-container"></div> <button type="submit">Submit</button> </form> ); }; export default FormWithCaptcha;
Class Component
If you’re using class components, use componentDidMount for the initial load and componentDidUpdate to detect route changes:
import React from 'react'; import { withRouter } from 'react-router-dom'; class FormWithCaptcha extends React.Component { captchaContainerRef = React.createRef(); initCaptcha = () => { if (window.__challenger?.callPageRequest) { window.__challenger.callPageRequest(); } else { setTimeout(this.initCaptcha, 150); } }; componentDidMount() { this.initCaptcha(); } componentDidUpdate(prevProps) { // Re-initialize when navigating back to this page if (this.props.location.pathname !== prevProps.location.pathname) { this.initCaptcha(); } } render() { return ( <form> {/* Your form fields */} <div ref={this.captchaContainerRef} className="captcha-container"></div> <button type="submit">Submit</button> </form> ); } } // Wrap with withRouter to access location props export default withRouter(FormWithCaptcha);
Key Notes
- Script Loading: Make sure the third-party captcha script is included in your
public/index.html(or loaded dynamically) sowindow.__challengeris available when your component runs. - Retry Logic: The
setTimeoutfallback handles cases where the script loads slower than your component mounts. You can adjust the delay or add a max retry count if needed. - Container Ref: Using a ref for the captcha container ensures we only initialize the captcha after its DOM element exists, which is a good practice for third-party UI components.
内容的提问来源于stack exchange,提问作者JPT

