David Pell
David Pell

Reputation: 939

React calling a method on load only once

I'm new to Hooks and have been encountering some cases that have been sending me chasing my tail.

Hope someone can explain or provide solutions that make sense to me:

  1. Loading a method only once on mount of a component is confusing. I tried this method, it works, but don't understand it. Can someone explain this to me:

    const useMountEffect = fun => useEffect(fun, [])
    
    useMountEffect(() => {
      if (!isEdit) handleAddRow()
    })
    
    const handleAddRow = () => {
      let appendArr = [...listArr, '']
      setListArr(appendArr)
    }
    

Following this thread: How to call loading function with React useEffect only once

I tried just using useEffect without dependency and eslint does not like that and they recommend adding a skip next line which seems kind of hacky:

// eslint-disable-next-line

Upvotes: 61

Views: 150939

Answers (3)

Prithwee Das
Prithwee Das

Reputation: 5226

If I'm correct you want something similar to the componentDidMount life-cycle method. The way to do that is:

function MyComponent(props){
    useEffect(()=>{
        // do stuff here...
    }, []) // <-- empty dependency array
    return <div></div>
}

To understand what's happening you'll need to understand how the useEffect hook works. Using the useEffect hook without any dependencies will trigger the effect every time some state or prop changes and causes a re-render; however, if we pass an empty array as a dependency it will mark the effect as not dependent on anything else, so it will only trigger when the component mounts.

Upvotes: 190

Jonathan Irwin
Jonathan Irwin

Reputation: 5747

The empty array [] argument tells useEffect() to run only once

It will run only once on mount, like componentDidMount used to

Explanation:

useEffect() takes 2 arguments - your function and an array of dependencies

useEffect(
    yourFunction, // <- function that will run on every dependency update
    [] // <-- empty dependency array
) 

The dependency array argument tells it when to run your function. If the dependencies don't change it won't run again. If dependencies do update it will run your function again.

If you pass in an empty array (no dependencies) then the function will only run on mount.

ESLint missing dependency error

React Hook useEffect has a missing dependency: 'xxx'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

The reason for the ESLint rule is that useEffect() is designed to run on every dependency update it will expect you to add all the dependencies to that array.

To ignore this you can add above the dependency array line:

// eslint-disable-next-line react-hooks/exhaustive-deps

Note: You almost never want to ignore the error


Note that on React 18 Strict Mode + Dev mode useEffect() will be called twice - read more about it here

Upvotes: 47

Mr Patience
Mr Patience

Reputation: 2180

For anyone looking to execute a function once per whole App (globally), this could be a solution:

if (typeof window !== 'undefined') { // Check if we're running in the browser.
   // ✅ Only runs once per app load
  checkAuthToken();
  loadDataFromLocalStorage();
}

function App() {
  // ...
}

Source / extended explanation here.

Upvotes: 12

Related Questions