如何使用 React Hook 在 React 组件中引用和加载 Javascript 文件

Posted

技术标签:

【中文标题】如何使用 React Hook 在 React 组件中引用和加载 Javascript 文件【英文标题】:How to reference and load Javascript file(s) inside a React Component using a React Hook 【发布时间】:2020-11-19 13:30:38 【问题描述】:

我是 React 的新手,我正在尝试使用一个名为 useEffectReact Hook 来在 javascript 中加载一个小脚本。 javascript 代码正在获取完整的当年,我试图在我网站的 FooterBottom 组件中调用它。我正在使用 tailwindcss 来制作这个 React 应用程序的样式。我见过一些使用这种方法的解决方案,例如:Adding script tag to React/JSX 和 How do i use external script that i add to react JS?。

我避免使用 componentDidMount(),因为我想学习如何使用 React Hooks 来使用它。非常感谢任何帮助。

Javascript: fullYear.js

var d = new Date();
var n = d.getFullYear();

document.write(d);

React Hook: useScript.js

import  useEffect  from 'react'

const useScript = function (file) 
  useEffect(() => 
    const script = document.createElement('script');

    script.src = file;
    script.type = 'type/javascript';
    script.async = true;
    script.onload = () => this.scriptLoaded();

    document.body.appendChild(script);

  , [file]);
;
export default useScript;

React 组件: FooterBottom.js

import React from 'react'
import useScript from './hooks/useScript.js'

const mystyle = 
  visibility: 'visible'
;

const MyComponent = props => 
  useScript('../assets/fullYear.js')


export default function FooterBottom() 
  return (
    <div className="footer-bottom">
      <div className="container items-center mx-auto ">
        <div style=mystyle className="bg-gray-800 text-center text-white wow zoomIn">
          <p>Copyright &copy; MyComponent(), All Rights Reserved.</p>
          <div className="footer_copyright">
            Designed by <a href="https://tailwindcss.com/">tailwindcss.com</a>
          </div>
        </div>
      </div>
    </div>
  );

【问题讨论】:

【参考方案1】:

您似乎在使用此脚本只是为了向您提供最近一年的版权。与尝试做你目前正在做的事情相比,使用以下内容要干净得多。

import React from 'react'

export default function FooterBottom() 
 const currentYear = new Date().getFullYear();

 return (
   <div className="footer-bottom">
     <div className="container items-center mx-auto ">
       <div style=mystyle className="bg-gray-800 text-center text-white wow zoomIn">
         <p>Copyright &copy; currentYear, All Rights Reserved.</p>
         <div className="footer_copyright">
           Designed by <a href="https://tailwindcss.com/">tailwindcss.com</a>
         </div>
       </div>
     </div>
   </div>
 );

现在我了解到您正在尝试学习如何使用钩子,所以我会稍微解释一下。

默认情况下,useEffect 中的任何内容都会在组件刷新时随时运行(称为重新渲染)。组件通常只会在自身或父状态发生变化时重新渲染。

useEffect 总是在第一次加载组件时运行一次,但我们也可以使用作为参数传递的数组来控制使 useEffect 触发的原因。例如,传递一个空数组 [] 将使 useEffect 在第一次渲染时运行一次。 在您的情况下,传递 [file] 意味着 useEffect 块内的代码将file 发生更改时执行

看看下面的代码。您会注意到我有 2 个状态正在更新。左键将更新计数,右键将更新 countTwo。您还会注意到有多个 useEffect 块。可以这样做来控制更新时要运行的内容。

如你所见,第一次 useEffect 只会将代码块第一次 渲染 App 组件,就是这样。

每次重新渲染 App 时都会执行第二个 useEffect。当按下任何按钮时,应用会重新渲染,因为它会更新 count 或 countTwo。

第三个 useEffect 将在 App 重新渲染时执行,但仅在 countTwo 更改时执行。

所以即使你按下左键,第三个 useEffect 也不会运行。只有第二个。但是如果你按下右键,第三个 useEffect 会在第二个 useEffect 之外运行。

import React,  useEffect  from "react";
import "./styles.css";

export default function App() 
  const [count, setCount] = React.useState(0);
  const [countTwo, setCountTwo] = React.useState(0);

  // THIS WILL ONLY RUN ON FIRST LOAD
  useEffect(()=> 
    console.log("I will only run on first component load!")
  ,[])

  // THIS WILL RUN ANYTIME THE APP RE-RENDERS
  useEffect(() => 
    console.log("App was re-rendered, and count was updated");
  );

  // THIS WILL ONLY RUN WHEN THE APP RE-RENDERS AND countTWO
  // IS UPDATED
  useEffect(() => 
    console.log("App was re-rendered, and countTwo was updated");
  , [countTwo]);

  return (
    <div className="App">
      <button onClick=() => setCount(count + 1)>Count: count</button>

      <button onClick=() => setCountTwo(countTwo + 1)>
        Count2: countTwo
      </button>
    </div>
  );


https://codesandbox.io/s/distracted-chatterjee-xznxd?file=/src/App.js

这样想,useEffect中运行的代码,就是组件刷新带来的‘效果’。我们可以控制哪些变化会触发效果,以及当不同的变量/状态更新时会发生什么不同。

最后,为什么你的代码不工作也是因为这不是你使用外部 javascript 文件的方式。

您需要在外部文件中创建一个函数,然后将其导出。然后你将它导入到你的 react 项目中。

示例如下:

Javascript:fullYear.js

export default function getYear() 
  return new Date().getFullYear();

React 组件:FooterBottom.js

import React from 'react'
import getYear from './fullYear'

export default function FooterBottom() 
  return (
    <div className="footer-bottom">
      <div className="container items-center mx-auto ">
        <div style=mystyle className="bg-gray-800 text-center text-white wow zoomIn">
          <p>Copyright &copy; getYear(), All Rights Reserved.</p>
          <div className="footer_copyright">
            Designed by <a href="https://tailwindcss.com/">tailwindcss.com</a>
          </div>
        </div>
      </div>
    </div>
  );

希望这是对外部文件如何工作以及 useEffect 如何工作的一个很好的解释。

【讨论】:

我明白了。我试图做的是将我的 javascript 代码“注入”到组件中,认为这可能是保持我的代码更清洁的唯一方法,同时在运行时更有效地加载。因此,如果我想将更多 js 文件加载到我的组件中,我会使用 useEffect 这样做,因为我必须卸载它们以防止网站呈现时进一步延迟。这就是为什么我使用了一个简单的最近一年的 js 代码。从 useEffect 的工作原理来看,我认为这个钩子只有在应用程序呈现而不是整个网站本身时才有用。

以上是关于如何使用 React Hook 在 React 组件中引用和加载 Javascript 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用React Hook

react的hook踩坑,useState的set方法不生效问题。

如何使用 React Hook 在 React 组件中引用和加载 Javascript 文件

如何使用 react-hook-form 有条件地禁用提交按钮?

React 钩子表单:如何在 React Hook 表单版本 7.0 上使用 onChange

在 React 中,如何使用 hook useState 来设置数据?