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

Next.js中如何在点击事件中调用自定义Hook?外部库调用失败

在React onClick事件中调用Daum Postcode自定义Hook失效的解决办法

问题描述

我需要使用Daum Postcode外部库,但调用出现问题。以下是自定义Hook代码:

const useDaumPostTest = () => {
  const Test = (asdsa: string) => {
    console.log(asdsa)
    const Element = (
      <>
        <Script defer src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js" strategy="beforeInteractive" />
        <Script>
          {
`      new daum.Postcode({
      oncomplete: function(data) {
         }
      }).open();
  `}
        </Script>
      </>
    )
    return Element
  }
  return {Test}
}

export default useDaumPostTest

当直接在组件中渲染Test返回的内容时(如{test})可以正常工作,但将Test函数放在点击事件处理函数handleClicks中调用时却无法正常运行。请问如何在onClick事件中使用该自定义Hook?

解决思路与代码调整

当前Hook的设计逻辑存在问题:Test函数返回的是包含<Script>的JSX元素,只有当这些元素被渲染到DOM中时,脚本才会加载并执行弹窗逻辑。但在点击事件里调用Test()只是得到了JSX对象,并没有将其挂载到DOM,所以不会触发任何效果。

正确的做法是将脚本加载和弹窗触发逻辑分离:提前加载脚本(或按需动态加载),在点击事件中直接调用Daum Postcode的API。

修改后的自定义Hook(通用版,不依赖框架特定组件)

import { useEffect, useState } from 'react';

const useDaumPostTest = () => {
  const [isScriptLoaded, setIsScriptLoaded] = useState(false);

  useEffect(() => {
    // 检查脚本是否已全局加载
    if (typeof window !== 'undefined' && window.daum?.Postcode) {
      setIsScriptLoaded(true);
      return;
    }

    // 动态创建脚本标签加载Daum Postcode库
    const script = document.createElement('script');
    script.src = '//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js';
    script.defer = true;
    script.onload = () => setIsScriptLoaded(true);
    script.onerror = () => console.error('Daum Postcode脚本加载失败');

    document.body.appendChild(script);

    // 组件卸载时清理脚本(可选)
    return () => script.parentNode?.removeChild(script);
  }, []);

  const openPostcode = (param: string) => {
    console.log(param);
    if (!isScriptLoaded) {
      console.error('Daum Postcode脚本未加载完成,请稍后重试');
      return;
    }
    
    // 直接调用Daum地址选择器API
    new window.daum.Postcode({
      oncomplete: function(data) {
        // 这里添加地址选择完成后的处理逻辑,比如填充表单
        console.log('选中的地址数据:', data);
      }
    }).open();
  };

  return { openPostcode };
};

export default useDaumPostTest;

组件中使用方式

import useDaumPostTest from './useDaumPostTest';

const AddressComponent = () => {
  const { openPostcode } = useDaumPostTest();

  return (
    <button onClick={() => openPostcode('test参数')}>打开地址选择弹窗</button>
  );
};

export default AddressComponent;

关键说明

  • 脚本通过动态创建<script>标签加载,确保在组件挂载时就开始加载,避免点击时才加载导致的延迟。
  • 通过isScriptLoaded状态判断脚本是否加载完成,防止调用API时出现daum未定义的错误。
  • openPostcode函数直接在点击事件中调用,无需返回JSX,逻辑更清晰,符合事件处理的常规写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:29:54