Denver Dang
Denver Dang

Reputation: 2615

Initiate function on page load

I have a function that gets some data when it is initiated. This can be done by a click even on a button, e.g.:

<button type="button" onClick={fetchData}>Get data</button>

Basically it is just a function given by:

function fetchData(e) {
    e.preventDefault();
    <something POST to get data>
}

All of this is working as intended. However, the data is only fetched when the button is clicked. I would like for the data to be fetched on load as well so there is actually some data presented before the button is clicked.

I thought I could just say:

useEffect(() => {
    fetchData()
}, [])

But that doesn't seem to work. However, if I take everything inside the function, and replace it with the fetchData() in the useEffect, then it works. But I don't feel like changing stuff twice every time the function needs updates etc.

So what am I doing wrong ?

Upvotes: 0

Views: 62

Answers (1)

Terry
Terry

Reputation: 66123

That is because when you're calling fetchData() in useEffect, no argument is being provided to the function. Yet in the function you are expecting the first argument to be present and calling it with e.preventDefault(). Since e will be undefined, attempting to access a key/property inside undefined will throw an error.

There are two solutions:

  1. Only invoke functions stored in e when it is not undefined
  2. Write a separate handler for the click event binding

Solution 1: Use optional chaining

By first checking if e is null or undefined, we can prevent attempting to access a key/property on it:

function fetchData(e) {
    e?.preventDefault();
    // Additional fetching logic
}

If you want to also support browsers that do not support optional chaining, then using the logical AND operand (&&) to perform lazy evaluation / short-circuiting will also work:

function fetchData(e) {
    e && e.preventDefault();
    // Additional fetching logic
}

Solution 2: Separate event handlers for button

Remove e from your fetchData function completely:

function fetchData() {
    // Additional fetching logic
}

...and prevent the default event at the level of the click handler:

const onClick = (e) => {
    e.preventDefault();
    fetchData();
}

<button type="button" onClick={onClick}>Get data</button>

Upvotes: 2

Related Questions