I'm new in Hooks. I coded a project with componentDidMount
.
Now I'm learning about hooks and rewriting this project with hooks. I want to fetch the data and print it on the console first.
However, it renders 3 times. It is probably because I used 2 setState
in useEffect
. However, in one of them I set the data to data array and in the other I keep the loading value for spinner control. How can I use useEffect
like componentDidMount
just one time to pull data and set my states?
When I write the console into useEffect
, "React Hook useEffect has a missing dependency: 'data'." warning and returns an empty list.
Btw I deleted strictmode.
import React, { useState, useEffect } from "react";
import axios from "axios";
function App() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
const fetchData = async () => {
const { data } = await axios.get("/data/data.json");
setData(data);
setLoading(false);
};
fetchData();
}, []);
console.log(data);
return <div className="App">App</div>;
}
export default App;
I think having the data
variable twice might be causing a conflict with the linter. You can rename your data coming from your API call to prevent the warning: "React Hook useEffect has a missing dependency: 'data'."
Your component will re-render on each state update, but the useEffect
will only run when your dependencies change. Since they aren't going to change, the API call only happens once.
To prove it, you can move the console.log(result)
in your useEffect
and see it only logs once. However, make sure you call it on your result
and not data
, because the state won't be updated until the next render after calling setData
.
import React, { useState, useEffect } from "react";
import axios from "axios";
function App() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
const fetchData = async () => {
const { data: result } = await axios.get("/data/data.json");
setData(result);
setLoading(false);
console.log(result); // runs once
};
fetchData();
}, [setData, setLoading]);
console.log(data); // runs 3 times
return <div className="App">App</div>;
}
export default App;