reactjs 如何创建一个定制的React钩子并合并来自我的(辅助)函数的逻辑

kmbjn2e3  于 2023-01-25  发布在  React
关注(0)|答案(1)|浏览(104)

我创建了以下两个函数,用于在React应用中 * 添加 * 和 * 删除 * 外部src和<script>标记:

type Args = {
    src: string;
    id: string;
    onLoad?: () => void;
  };

  const addScript = ({ src, id, onLoad }: Args) => {
    const existing = document.getElementById(id);
    if (existing) {
      return existing;
    }
    const script = document.createElement('script');
    script.src = src;
    script.id = id;
    script.async = true;
    script.onload = () => {
      if (onLoad) {
        onLoad();
      }
    };
    document.body.appendChild(script);
    return script;
  };

  const removeScript = ({ id }: { id: string }) => {
    const script = document.getElementById(id);
    if (script) {
      document.body.removeChild(script);
    }
  };

我可以这样使用它:

useEffect(() => {
    const script = addScript({
      src: `https://domain/js/main.js`,
      id: 'ad-script',
      onLoad: () => {
        console.log('Script loaded!');
      },
    });
    return () => removeScript({ id: script.id });
  }, [id]);

既然我在这里使用了useEffect钩子,我如何创建一个自定义的React钩子来返回上面的逻辑,并且我可以使用:useScript('https://domain/js/main.js', 'my-script' );

fsi0uk1n

fsi0uk1n1#

自定义钩子获得了addScript所需的相同参数,它将onLoad存储在一个ref中,因此onLoad发生变化时useEffect不会触发,这样就不需要用useCallback Package onLoad

const useScript = ({ src, id, onLoad }: Args) => {
  const onLoadRef = useRef(onLoad);

  useEffect(() => {
    const script = addScript({ src, id, onLoad: onLoadRef.current?.() });
    
    return () => removeScript({ id: script.id });
  }, [src, id]);
}

相关问题