Reputation: 174
I'm trying to get the value of googleToken
inside a <div>
in the return
of my React Component. The value is already updated, but it's the initial state here in the return
, therefore, it always shows null
const Layout = props => {
let googleToken = null;
useEffect( () => {
fetchGoogleToken();
}, [])
const fetchGoogleToken = async () => {
await api
.get("/google_token")
.then((response) => {
console.log('google_token: ' + response.data.google_token);
googleToken = response.data.google_token;
console.log('google_token updated: ' + googleToken);
})
.catch((error) => console.log(error));
};
const getGoogleToken = (res) => {
console.log(res);
setGoogleToken(res.accessToken);
saveGoogleTokenInDB();
};
const saveGoogleTokenInDB = async () => {
await api
.post("/fit-auth", {google_token : googleToken})
.then((response) => {
console.log(response);
})
.catch((error) => console.log(error));
};
return (
<div className={classes.googleButton} style={{display: googleToken === null ? 'block' : 'none'}}>
<h3>{googleToken}</h3>
<div/>
}
Any ideas on why I can't get the updated value?
Upvotes: 0
Views: 217
Reputation: 1160
It is right to use useEffect hook for fetching. But the result must be kept into state. And when you ask react to update state, you can not watch changes on the next line of code using console.log because setState is async function and it will be executed later on.
// this will never work as you might be expected:
setState(newState)
console.log(state)
To catch state updates always use useEffect hook as in example below:
useEffect(() => {
console.log(state)
}, [state])
Also, avoid using inline styles for showing / hiding your components. Check the official conditional rendering recommendations. The final code is going to look like this:
const Layout = props => {
const [googleToken, setGoogleToken] = useState(null)
useEffect( () => {
fetchGoogleToken();
}, [])
// you can watch how state changes only using useEffect:
useEffect(() => {
console.log('google_token updated: ' + googleToken)
}, [googleToken])
const fetchGoogleToken = async () => {
await api
.get("/google_token")
.then((response) => {
console.log('google_token: ' + response.data.google_token);
setGoogleToken(response.data.google_token);
})
.catch((error) => console.log(error));
};
// conditional rendering:
if (!googleToken) return <span>Fetching token...</span>
return (
<div className={classes.googleButton}>
<h3>{googleToken}</h3>
<div/>
)
}
Hope you will find this helpful.
Upvotes: 1
Reputation: 1
The issue is that when the value of googleToken is updated the component is not notified about this. Since the component is not notified about the change it still believes that the value is still the initial value and it does need to change anything in DOM.
To solve this issue try using states or just force a rerender once the function is executed.
Upvotes: 0