Reactjs useeffect data appear twice

I don’t get it, could someone please help me with this problem, why is my console.log() in my randomFunc() log out data twice when I visit “Hello” page/component?

App.js

import { useState } from "react";
import { Switch, Route, Link } from "react-router-dom";
import Home from "./Home";
import Hello from "./Hello";

export default function App() {
  const [data, setData] = useState();

  const randomFunc = (dataFromHelloComponent) => {
    setData(dataFromHelloComponent);
    console.log(dataFromHelloComponent); /* <====  When I click "Go to Hello!" Link, this line log out data twice!? */
  };

  return (
    <div className="App">
      <Link to="/hello">Go to Hello!</Link>
      <Switch>
        <Route path="/" exact component={Home} />
        <Route
          path="/hello"
          render={(props) => (
            <Hello {...props} randomFunc={randomFunc} data={data} />
          )}
        />
      </Switch>
    </div>
  );
}

Hello.js

import { useEffect } from "react";

export default function Hello({ randomFunc }) {
  useEffect(() => {
    randomFunc("Some random data!");
  }, [randomFunc]);

  return (
    <div className="hello">
      <h1>Hello World!</h1>
    </div>
  );
}

Hi, I guess that’s because your effect hook in Hello.js runs twice: On mount and when receiving the props, because you put randomFunc in your dependency array.
Since you receive the function synchronously, I don’t think that adding the props to the dependency array is necessary. What if you leave the dependency array empty?

Hi @mirja_t when I have “randomFunc” in Hello.js “useEffect” dependency, I get this in my browser console:
Some random data!
Some random data!

and if I remove “randomFunc” from Hello.js “useEffect” dependency, I get this in my browser console:
Some random data!
React warning: React Hook useEffect has a missing dependency: ‘randomFunc’. Either include it or remove the…

I still don’t quite get it :pensive: :frowning: , so the first “Some random data!” that log out in my browser console is because of Hello.js component’s initial render right? but why does it log out “Some random data!” second time?

Yes.

Because it’s called a second time when the state in the dependency array is updated. When you take it out, it logs only once, right?
Why do you call the function in the child component? I assume the argument for the function call will come from the child component?
Then you could use that state for the dependency array and use a conditional statement for calling the function.
The issue with the warning about the missing dependency is answered here:
https://stackoverflow.com/questions/55840294/how-to-fix-missing-dependency-warning-when-using-useeffect-react-hook

Do you mean something like this:
Hello.js

useEffect(() => {
    if (!data) {
        randomFunc("Some random data!");
    }
}, [randomFunc, data]);

After reading your last reply post I kind get it why it log out “Some random data!” second time, “setData()” is the part of the code that cause the “randomFunc” to run second time (so it log out “Some random data!” second time) but when “randomFunc” run second time “setData()” execute again right? how come it’s not causing infinite loop?

Sorry reactjs beginner here

No, I don’t think so. You call randomFunc in App.js only once. If that was the reason, it would log twice even if you took out the props from the dependency array.

Yes, but I saw that you defined data in the parent component. If you get both your data and the function from the parent component, why would you pass both through to the child component to call the function there?

I am going to get a data(param) from url and pass back to parent when I visit Hello.js page/component. :slight_smile:

But I found out that if I remove “setData()” from “randomFunc” and still keep the “randomFunc” in “useEffect()” dependency array, it only logs out “Some random data!” once, so somehow when using “setData()” it’s triggering Hello.js “useEffect()”? But how come I am not getting infinite loop tho if “randomFunc” is re-executing…?

Ok, I see that you pass “data” as props to Hello.js as well. That might cause the component to rerender. What if you take that out?

App.js

<Route 
    path='/hello' 
    render={(props) => (
	   <Hello {...props} randomFunc={randomFunc} data={data} /> /* <=== take this data out */
	)}
/>

I took out the data={data} but still the same, getting two “Some random data!” in my browser console

Then I’m running out of ideas. Maybe someone else knows better.