Reputation: 67
I am new to React and I am trying to use a React Hook called useEffect to load a small script in Javascript. The javascript code is obtaining the full current year and I am attempting to call that inside of my FooterBottom component of my website. I am using tailwindcss to make the styling of this React app. I've seen a couple of solutions using this method such as the following: Adding script tag to React/JSX and How do i use external script that i add to react JS?.
I am avoiding componentDidMount() because I want to learn how to use this using React Hooks. Any help is much appreciated.
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 Component: 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 © {MyComponent()}, All Rights Reserved.</p>
<div className="footer_copyright">
Designed by <a href="https://tailwindcss.com/">tailwindcss.com</a>
</div>
</div>
</div>
</div>
);
}
Upvotes: 1
Views: 7687
Reputation: 238
It looks like you're using this script to simply give you the latest year in your copyright. It is much cleaner to use the following, versus trying to do what you are currently doing.
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 © {currentYear}, All Rights Reserved.</p>
<div className="footer_copyright">
Designed by <a href="https://tailwindcss.com/">tailwindcss.com</a>
</div>
</div>
</div>
</div>
);
}
Now I understand you're trying to learn how to use hooks, so I will explain it a little bit.
by default, anything inside useEffect is ran anytime that component refreshes (called re-rendering). A component will usually only re-render when itself or a parent state changes.
useEffect is always ran once the first time a component is loaded, but we can also control what makes useEffect trigger using an array passed as an argument. For example, passing an empty array []
will make useEffect run once on first render.
In your case, passing [file]
means the code inside that useEffect block will only execute when there is a change to file
Take a look at this following code. You will notice I have 2 states being updated. Left button will update count, and right button will update countTwo. You'll also notice there are multiple useEffect blocks. This can be done to control what to run when something is updated.
As you can see, the first useEffect will only the code block the first time the App component is rendered, and that's it.
The second useEffect will execute every time the App is re-rendered. The app is re-render when any of the buttons are pressed because it updates either count, or countTwo.
The third useEffect will execute when the App is re-rendered but ONLY if countTwo changed.
So even though you press the left button, the third useEffect will not run. Only the second. But if you press the right button, the third useEffect will run in addition to the second 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
Think of it like this, The code running in the useEffect, is the 'effect' caused by the component refreshing. We can control what change triggers the effect, and what have different happen when different variables / states get updated.
Lastly, why your code isn't working is also because this is not how you use external javascript files.
You need to create a function in your external file and then export it. You then import it in your react project.
And example would be the following:
Javascript: fullYear.js
export default function getYear() {
return new Date().getFullYear();
}
React Component: 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 © {getYear()}, All Rights Reserved.</p>
<div className="footer_copyright">
Designed by <a href="https://tailwindcss.com/">tailwindcss.com</a>
</div>
</div>
</div>
</div>
);
}
Hope this was a good explanation for how external files work, and how useEffect works.
Upvotes: 4