So I have the following situation when using a useEffect
that calls a functions that depends on state.
Example:
// INSIDE APP COMPONENT
const [someState, setSomeState] = React.useState(0);
const [someTrigger, setSomeTrigger] = React.useState(false);
function someFunction() {
return someState + 1;
}
React.useEffect(() => {
const newState = someFunction(); // 'someFunction' IS BEING CALLED HERE
setSomeState(newState);
},[someTrigger])
QUESTIONS:
In this case, should I declare someFunction
inside the useEffect()
or is it safe to keep it outside (but inside component's body)?
I could add it to the dependency
array, but it will hurt the redability of my code, since I want to focus on the trigger
.
Since the useEffect()
will run after a fresh render, is it safe to assume that it will have fresh copies of the functions that I'm calling inside of it?
Is there a basic rule of when you should declare functions inside the useEffect
hook or when is it mandatory that you add it to the dependency array?
EDIT: Note that it's necessary that the useEffect
has fresh copies of those functions, since those functions need to access some fresh up-to-date state
variable.
NOTE:
This code triggers the following eslint warning on CodeSandbox. Although it works just fine.
React Hook React.useEffect has a missing dependency: 'someFunction'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)eslint
REAL CASE SCENARIO:
This is a simplified example. In my real case, this is a product search page with filters components. So when I click on a filter to activate it (let's say, price <= 50
), I'm triggering a useEffect()
that is "listening" for the activePriceFilters
state variable. That effect then calls a function (someFunction
in the example) that will calculate the filteredList
and will set the new productList
state with the new filteredList
.
SNIPPET
function App() {
const [someState, setSomeState] = React.useState(0);
const [someTrigger, setSomeTrigger] = React.useState(false);
function someFunction() {
return someState + 1;
}
React.useEffect(() => {
const newState = someFunction();
setSomeState(newState);
},[someTrigger])
return(
<React.Fragment>
<div>I am App</div>
<div>My state: {someState}</div>
<button onClick={()=>setSomeTrigger((prevState) => !prevState)}>Click</button>
</React.Fragment>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
useEffect
– Sankaran