Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where should I declare functions that are called inside a useEffect() hook?

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"/>
like image 402
cbdeveloper Avatar asked Jul 02 '19 10:07

cbdeveloper


People also ask

How do you use useEffect hook inside a function?

useEffect enables you to run something whenever the the component is rendered or when a state changes. Having that inside of a function that is called on click makes it useless. useEffect should call other functions, but should never be called from within a function.

How do you call a function defined in useEffect?

If we just want to run the useEffect function after the initial render, as a second argument, we can give it an empty array. If we pass a second argument (array), React will run the callback after the first render and every time one of the elements in the array is changed.

Can you put a useEffect inside a function?

Why is useEffect called inside a component? Placing useEffect inside the component lets us access the count state variable (or any props) right from the effect. We don't need a special API to read it — it's already in the function scope.

What does useEffect () hook do in React?

The useEffect Hook allows you to perform side effects in your components. Some examples of side effects are: fetching data, directly updating the DOM, and timers. useEffect accepts two arguments. The second argument is optional.


Video Answer


1 Answers

A decision to define a function within or outside of useEffect depends on where all the functions is called.

If your function is called only from within the useEffect then it makes sense to define it within the useEffect.

However is the same function is being called from within useEffect as well as other event handlers or other effects, you need to define it outside of useEffect

PS. in your case you are just updating the state for which you needn't define a separate function

function App() {
  
  const [someState, setSomeState] = React.useState(0);
  const [someTrigger, setSomeTrigger] = React.useState(false);
  

  React.useEffect(() => {
    setSomeState(oldState => oldState + 1);
  
  },[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"/>

As far as you scenario is concerned, you would write it like

useEffect(() => {
    const calcVal = (oldState) => {
         // calculate previous state based on oldState
    }

    setSomeState(calcVal);
}, [activePriceFilters])
like image 109
Shubham Khatri Avatar answered Oct 14 '22 21:10

Shubham Khatri