Before going any further know that this post consist of two part: Why do this? and How do this?
Since i am writing this post as an supplementary post of my other post (NextJS - Access window and localStorage) i'm going to first explain How and then Why
How
Create a component that contains only logic and return no JSX
. In other word all logic and no view(UI):
Following example will log a message in console when it's called
const ConsoleLogger = () => {
console.log("Hello World");
return null; // return value must be JSX (our UI or view) that is null.
};
export default ConsoleLogger;
You can even pass a message to print:
const ConsoleLogger = ({massage}) => {
console.log(massage);
return null; // return value must be JSX (our UI or view) that is null.
};
export default ConsoleLogger;
Now lets take it a step further and take advantage of react features such as useEffect
hook and do some practical things.
Following example shows how to subscribe an EventListener
to our browser window
object:
// components/Scroll.js
import { useEffect } from "react";
const Scroll = () => {
useEffect(() => {
indow.addEventListener("scroll", () => { console.log("scroll!"); });
}, []); // empty dependencies array means "run this once on first mount"
return null; // it render nothing in page and only runs logics
};
export default Scroll;
Now need to add this component to your React Component Tree
// pages/index.js
import Scroll from "../components/Scroll";
const Home = () => (
<div style={{ minHeight: "1000px" }}>
<h1>Home</h1>
<Scroll />
<ConsoleLogger massage="Hello World" />
</div>
);
export default Home;
Note: We used useEffect
hook because some time (e.g. using Frameworks such as Next.JS and SSR
(Server-Side Rendering)) you do not have access to document
or window
properties such as local storage
(Read more here!). And you need to run such a code in run-time(rendering phase) and useEffect
hook will do so.
Why
There are instance that you need to run an JavaScript
statement that rely on React
features.
You might wondering why you need to change your code and not just using it in relevant components?
But what if there is no logical relation between them? For example Subscribing(registering) an EventListener
such as a "Scroll" event to your window
object?
As you can see this is not relevant to any component and it's a operation that apply globally with no dependency.
Or in some instance you want to simple change the way your code looks (calling it like React Components instead of calling a function)
const Home = () => (
<div>
<h1>Home</h1>
<SubToScroll /> vs {SubToScroll()}
</div>
);
export default Home;
Note: Make JavaScript logic Independent to components
useEffect
is a hook and it must be used in functional components.
But at the same time, it's wrong for our JS codes that are unrelated to a specific component to depend on them.
And it's also wrong to have duplicated statements all over our code.
So we have two options:
- Create global functions and export them.
- turn our initial JavaScript file into a true React component
Solution No. 1
is simple and it has its own downsides such as being unable to use or hard implementation of react hooks and etc.
So we recommend running your JS logical code as a react component.
Top comments (0)