I’m trying to set a variable with a simple GET database call. The database call is returning the data correctly, but the variable remains undefined after every re-render. Code is below… the getMyThing()
function in the useState()
function is working correctly and returning the data I want.
import { getMyThing } from '../../utils/databaseCalls' const MyComponent: React.FC = () => { const { id } = useParams(); const [myThing, setMyThing] = useState(getMyThing(id)); useEffect(() => { setMyThing(myThing) }, [myThing]); }
My thinking here was to use useState()
to set the initial state of the myThing
variable with the data returned from my database. I assume it’s not immediately working since a database call is asynchronous, so I thought I could use useEffect()
to update the myThing
variable after the response of the database call completes, since that would trigger the useEffect()
function because I have the myThing
variable included as a dependency.
What am I missing here? Thanks!
EDIT: Thanks for the answers everyone, but I still can’t get it to work by calling the getMyThing
function asynchronously inside useEffect()
. Is something wrong with my database call function? I guess it’s not set up to a return a promise? Here’s what that looks like:
export const getMyThing = (id) => { axios.get('http://localhost:4000/thing/' + id) .then(response => { return(response.data); }) .catch(function (error){ console.log(error); }) }
Advertisement
Answer
You should do all your side effects(fetching data, subscriptions and such) in useEffect
hooks and event handlers. Don’t execute async logic in useState
as you just assign the promise itself to the variable and not the result of it. In any case, it is a bad practice and it won’t work. You should either:
import { getMyThing } from '../../utils/databaseCalls' const MyComponent: React.FC = () => { const { id } = useParams(); const [myThing, setMyThing] = useState(null); useEffect(() => { const fetchData = async () => { const result = await getMyThing(id); setMyThing(result); }; fetchData(); }, [id, getMyThing]); }
Or if you don’t want to introduce an async
function:
import { getMyThing } from '../../utils/databaseCalls' const MyComponent: React.FC = () => { const { id } = useParams(); const [myThing, setMyThing] = useState(null); useEffect(() => { getMyThing() .then(result => setMyThing(result)); }, [id, getMyThing]); }
Also, take note of the [id, getMyThing]
part as it is important. This is a dependency array determining when your useEffect
hooks are gonna execute/re-execute.