Let's dive into React hooks. One thing to keep in mind is that hooks were introduced for functional components only. Hooks don't work inside classes.
Hooks are just functions responsible for certain behavior. In this article, we will be discussing useState and useEffect.
- useState
useState is a React hook used for managing state variables. We can declare a state variable and update it directly. useState is imported from the react module.
Here is an example of useState:
const [count,setCount] = useState(0)
Here, countis the name of the variable, and setCountis the name of the callback function that will update the state. useState(0) means we set 0 as the default value. 0 will be rendered initially, and after that, when we update the variable, the new value will be rendered.
Now let's take an example of a counter app to learn more
import { useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
const increase = () => {
setCount(count + 1);
};
const decrease = () => {
setCount(count - 1);
};
return (
<div>
<h1>count : {count}</h1>
<button onClick={decrease}>-</button>
<button onClick={increase}>+</button>
</div>
);
}
In the above code, we use setCountto update a new value, i.e., increasing the count by 1. Similarly, we can decrease the count value by 1. This is a basic way of writing code.
The problem arises when we use another setCountin the increase or decrease function. The count value ideally should decrease by 2, but this won't happen.
Add this code to the counter app, and you will see that the count will increase and decrease by 1 only:
const increase = () => {
setCount(count + 1);
setCount(count + 1);
};
const decrease = () => {
setCount(count - 1);
setCount(count - 1);
};
If we want to increase or decrease the count by 2, then we should pass a callback function:
const increase = () => {
setCount((prevCount) => prevCount + 1);
setCount((prevCount) => prevCount + 1);
};
const decrease = () => {
setCount((prevCount) => prevCount - 1);
setCount((prevCount) => prevCount - 1);
};
Here, setCounttakes a callback function that will track the previous value of countand then increase or decrease the count value.
Note: We passed 0as a default value. Since 0is a hard-coded value, it will run every time the component renders. To avoid rendering 0every time, pass a callback function that will return 0:
import { useState } from "react";
function value() {
console.log("render");
return 0;
}
export default function App() {
const [count, setCount] = useState(value());
const increase = () => {
setCount((prevCount) => prevCount + 1);
setCount((prevCount) => prevCount + 1);
};
const decrease = () => {
setCount((prevCount) => prevCount - 1);
setCount((prevCount) => prevCount - 1);
};
return (
<div>
<h1>count : {count}</h1>
<button onClick={decrease}>-</button>
<button onClick={increase}>+</button>
</div>
);
}
useState(value()) and useState(0) both work in the same way. Here, the value function will return 0 and log "render" every time. To avoid calling "render" every time, write useState(() => return 0). It will render only one time.
- useEffect
useEffect is used to perform side effects in components and is imported from the React module. By "side effects," we mean tasks such as fetching data or updating the DOM, etc.
useEffect takes two arguments: a function and optional dependencies (an array).
import { useEffect } from 'react';
useEffect(() => {
//code
}, [dependencies]);
The dependencies array ensures when the effect will re-run.
There are three cases of dependency arrays:
- No dependency array :
useEffectwill be called every time. Let's seeuseEffectin action:
import { useEffect, useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
console.log("called");
}, 2000);
});
return (
<div>
<h1>Count is called {count} times.</h1>
</div>
);
}
Here, after every 2 seconds, the count will increase by 1, and "called" will be logged in the console.
- Empty dependency array [] :
useEffectwill be called once,during initial render.
import { useEffect, useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
console.log("called");
}, 2000);
}, []);
return (
<div>
<h1>Count is called {count} times.</h1>
</div>
);
}
In the above code , we added an empty dependency array [].Now, useEffect will run only one time.
- Some value passed in the dependency array:
useEffectwill be called every time whenever the value passed in the dependency array changes. We can pass any number of values in the dependency array.
import { useEffect, useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
console.log("called");
}, 2000);
}, [count]);
return (
<div>
<h1>Count is called {count} times.</h1>
</div>
);
}
In the above code, count is passed in the dependency array. So whenever count is updated, useEffect will be called again. In the above code, the count will increase infinitely as every time count is updated, useEffect will be called again, and this will go on and on.
There is an effect cleanup function, which will stop the useEffect re-execution, as there may be a memory leak problem. The cleanup ensures that no unexpected behaviour occurs.
import { useEffect, useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setTimeout(() => {
setCount((count) => count + 1);
console.log("called");
}, 2000);
return () => clearInterval(timer);
}, [count]);
return (
<div>
<h1>Count is called {count} times.</h1>
</div>
);
}
Note: useEffect will at least run once in the initial render.
Top comments (0)