React , why is this useEffect being triggered on load?
By default, useEffect
always runs after the first render.
The dependency array in useEffect
lets you specify the conditions to trigger it. If you provide useEffect
an empty dependency array, it’ll run exactly once.
If you want to trigger only after setNumberOfPages is triggered for the first time then the way you're using it is right:
useEffect(() => {
if (numberOfPages != null) {
const newArr = splitArray(issues, numberOfPages);
console.log('new arr');
console.log(newArr);
}
}, [numberOfPages]);
Additionally, you can check out this awesome StackOverflow answer: https://stackoverflow.com/a/59841947/16420018
And this article by Dan Abramov:
https://overreacted.io/a-complete-guide-to-useeffect/
How to fix this Maximum depth exceeded error with useEffect and useState?
Because you are executing useEffect callback whenever data changes and you are changing data in useEffect callback.
Remove data as dependency.
Use this code to fix it
const SingleTable = () => {
const events = useSelector(state => eventsSelector(state));
const [data, updateData] = useState([]);
const [sortCol, updateSortCol] = useState(0);
const [sortDir, updateSortDir] = useState('ascending');
useEffect(() => {
const formattedArray = events ? formatLoss(events): [];
events && updateData(formattedArray);
}, [events]);
//...
Maximum depth exceeded while using useEffect
what you are doing here is fetching a product list and filtering it based on the query string and using that filtered list to render the UI. So ideally your filteredList
is just a derived state based on your queryString
and productList
. So you can remove the filterProducts
from your useEffect and move it outside. So that it runs when ever there is a change in the state.
function filterProducts (productName = '', productList = []) {
return productName.trim().length > 0 ? productList.filter((prod)=> {
return prod.title === productName;
}); : productList
}
function HomePage () {
const [productList, setProductList] = useState([]);
const [queryString, setQueryString] = useState('');
useEffect(() => {
if (queryString.trim() === "") {
Axios.get("http://localhost:3001/api/product/get-all").then((data) => {
setProductList(data.data);
});
}
}, [queryString]);
// query products is the derived state
const queryProducts = filterProducts(queryString, productList);
// Now instead of using productList to render something use the queryProducts
return (
{queryProducts.map(() => {
.....
})}
)
If you want the filterProducts
to run only on change in queryString
or productList
then you can wrap it in useMemo
const queryProducts = React.useMemo(() => filterProducts(queryString, productList), [queryString, productList]);
When to use useEffect?
You showed two different examples,
handleButtonClick
fires on Button 1
click, while useEffect
fires on every state change state (according to the dependency array).
In the next example, you notice that useEffect
will log on every button click (Button 1/2
), and handleButtonClick
will log only on Button 2
click.
import React, { useState, useEffect } from "react";
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`You rendered ${count} times`);
}, [count]);
const handleButtonClick = () => {
setCount(count + 1);
console.log(`You clicked ${count + 1} times`);
};
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Button 1</button>
<button onClick={handleButtonClick}>Button 2</button>
</div>
);
}
- Check similar question on
useEffect
use cases - Refer to
useEffect
docs
Why does useEffect dependencies on destructed props cause maximum update exceeded?
When ids
is passed as a prop, the only time the local ids
variable will have had its reference changed will be when the prop changes.
When it's not passed as a prop, the default assignment, since it runs inside the function, every time the function runs, produces a new empty array every time. So, if the function component updates once, it'll try to continue updating forever because the default empty array reference keeps changing.
One way to fix this would be to put the empty array outside the component. (Just make sure not to mutate, as always in React)
const emptyArr = [];
function Test1(props) {
const { ids = emptyArr } = props;
const [evenIds, setEvenIds] = useState<string[]>([]);
useEffect(() => {
const newEvenIds = ids.filter(id => id % 2 === 0);
setEvenIds(newEvenIds);
}, [ids])
return (<span>hello</span>)
}
State shouldn't be duplicated in more than one place though. useMemo
would be more appropriate than a separate state and useEffect
IMO.
const emptyArr = [];
function Test1(props) {
const { ids = emptyArr } = props;
const evenIds = useMemo(() => ids.filter(id => id % 2 === 0), [ids]);
return (<span>hello</span>)
}
Related Topics
Make React Useeffect Hook Not Run on Initial Render
How to Pass the Value (Not the Reference) of a Js Variable to a Function
How to Check If the User Can Go Back in Browser History or Not
How to Implement Routereusestrategy Shoulddetach for Specific Routes in Angular 2
Why Is 'Replace' Property Deprecated in Angularjs Directives
How to Figure Out the Highest Z-Index in Your Document
How to Format/Tidy/Beautify in JavaScript
Change Text Color Based on Brightness of the Covered Background Area
Formdata.Append("Key", "Value") Is Not Working
Why How to Use a Function Before It's Defined in JavaScript
How to Include a JavaScript Script File in Angular and Call a Function from That Script
Global Variables in JavaScript Across Multiple Files
How to Mock an Es6 Module Import Using Jest
Is This an Example of Variable Shadowing in JavaScript
How to Open a New Window and Insert HTML into It Using Jquery
Jquery $("#Radiobutton").Change(...) Not Firing During De-Selection