I'm have a problem with Context in React, in this context i load user data (like id, name, role etc) and in website it's work fine, problems starts on fetchToken function where i find firebase token and send it to backend:
const [userData, setUserData] = useState<any>([]);
const [isTokenFound, setTokenFound] = useState<boolean>(false);
const [userLoading, setUserLoading] = useState<any>(true);
useEffect(() => {
if (isAuth)
apiClient
.get("api/v1/user/params")
.then(({ data }) => {
setUserData(data);
setUserLoading(false);
fetchToken({
setTokenFound,
userData,
userLoading,
});
})
Here is fetchToken function where i have problem with userData:
export const fetchToken = ({setTokenFound, userData, userLoading}:FirebaseProps) => {
return getToken(messaging, { vapidKey: 'fake' }).then((currentToken) => {
if (currentToken) {
console.log("current token for client: ", currentToken);
setTokenFound(true);
console.log("firebase", userData);
// Track the token -> client mapping, by sending to backend server
// show on the UI that permission is secured
if (
userData.data.notification_token_needs_to_update ===
true
)
apiClient
.post(
`api/v1/user/${userData.data.id}/create-notification`,
{
push_notification_token: currentToken,
}
)
.then((response) => {
if (response.status === 204) {
console.log("token send to backend", {
push_notification_token: currentToken,
user_browser: browserAndOS,
});
}
})
.catch((error) => {
if (error.response && error.response.status === 422) {
} else {
console.error(error);
}
});
} else {
console.log(
"No registration token available. Request permission to generate one."
);
setTokenFound(false);
// shows on the UI that permission is required
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
// catch error while creating client token
});
}
It's doesn't seems like FCM problem, I'm just don't have context userData on first render and i don't understand why
There is console.log on first render:
And there is after i change some code in IDE and save it:
It's really annoying problem, i'm even tried save data to localStorage first, but it's undefined even then, looks like i don't see some fundamental thing here...
CodePudding user response:
setState is asynchronous. Not 100% sure if it will help.
const [userData, setUserData] = useState<any>([]);
const [isTokenFound, setTokenFound] = useState<boolean>(false);
const [userLoading, setUserLoading] = useState<any>(true);
useEffect(() => {
if (isAuth)
apiClient
.get("api/v1/user/params")
.then(({ data }) => {
setUserData(data); // asynchronous
setUserLoading(false); // asynchronous
fetchToken({
setTokenFound,
userData, // <- state has not been updated yet, you passing old state value []
userLoading, // <- same, you passing true
});
})
Just pass what you recieve from response.
const [userLoading, setUserLoading] = useState<any>(true);
useEffect(() => {
if (isAuth)
apiClient
.get("api/v1/user/params")
.then(({ data }) => {
setUserData(data);
setUserLoading(false);
fetchToken({
setTokenFound,
data,
false,
});
}, []) // Add empty dependency array, so this effect only runs on first render