16

I have the following code in FC component:

I just want to call the Api and Log the info when the component is mounted

The console.log is being called twice for empty array and twice for setting the same values.

import * as React from"react";
import Header from"../components/Header";
import Search from"../components/Search";
import Categories from"../components/Categories";
import Carousel from"../components/Carousel";
import CarouselItem from"../components/CarouselItem";
import Footer from"../components/Footer";
import "../assets/styles/App.scss";

const App = () => {
  const [videos, setVideos] = React.useState([]);

  React.useEffect(() => {
    fetch("http://localhost:3000/initalState")
      .then((response) => response.json())
      .then((data) => setVideos(data));
  }, []);

  console.log(videos);
  return (
    <div className="App">
      <Header></Header>
      <Search></Search>

      <Categories title="Mi Lista">
        <Carousel>
          <CarouselItem />
          <CarouselItem />
          <CarouselItem />
          <CarouselItem />
          <CarouselItem />
        </Carousel>
      </Categories>

      <Categories title="Tendencias">
        <Carousel>
          <CarouselItem />
          <CarouselItem />
        </Carousel>
      </Categories>

      <Categories title="Originales de Platzi Video">
        <Carousel>
          <CarouselItem />
        </Carousel>
      </Categories>

      <Footer />
    </div>
  );
};

export default App;

However, i got the following output:

enter image description here

Calling within useEffect:

  React.useEffect(() => {
    fetch("http://localhost:3000/initalState")
      .then((response) => response.json())
      .then((data) => {
        setVideos(data);
        console.log(videos);
      });
  }, []);

returns an empty array.

4
  • you are printing it outside. Try printing it within the useEffect callback. Commented May 10, 2020 at 2:32
  • Also verify there is only one <App/> component being mounted. Probably is but clearing the obvious first helps Commented May 10, 2020 at 2:34
  • Yes, just one App is being mounted. Commented May 10, 2020 at 2:52
  • @AmitJoki i just updated this post for printing inside useEffect callback, gives me an empty array. Commented May 10, 2020 at 2:54

2 Answers 2

50

I just realized I was rendering App in strict Mode, which invokes some events twice:

Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:

Class component constructor, render, and shouldComponentUpdate methods Class component static getDerivedStateFromProps method Function component bodies State updater functions (the first argument to setState) Functions passed to useState, useMemo, or useReducer

I had this:

ReactDOM.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      document.getElementById("root")
    );

Now

ReactDOM.render(<App />, document.getElementById("root"));

It's solved.

Sign up to request clarification or add additional context in comments.

2 Comments

you helpme very much
Removing StrictMode should be the last choice. For a more detailed answer, you may visit stackoverflow.com/questions/72238175/….
2

you can use UseCallback to avoid an additional run below is the sample code.

Note: If you directly call setTimeout/server calls inside use effect without wrapping in useCallback , it will be called twice

const App = () => {
  const [myData, setMyData] = React.useState([]);


  const getData = useCallback ( () => { 
    setTimeout(() => {
      console.log("Inside setTimeOut");
      setMyData("HEllo");
    }, 2000);

  }, [] )

  useEffect(() => {
    getData()
     console.log("Inside UseEffect",myData);
   },[getData]);


  return (
    <div className="App">
     Inside my App {myData}
    </div>
  );
}

export default App;

Output:

Inside UseEffect  [printed just once]

4 Comments

I understand. Should i use console.logs outside the useEffect hooks? Same level as useEffect, return and getData?
Nope. Then it will have more cycles , as getdata will have new data which will render again and prints log again. By wrapping i useEffect and adding dependency it will not run unless dependency changes
I have removed all the myData dependencies and kept the other console prints. It prints Inside UseEffect twice
You're a genius!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.