React Hook does not set on first API call - react-native

So I am sure I am messing something up, but I am not super skilled at API.
So I am trying to make an API call to check if the user exists, if user exists then move about business, if not then do other stuff.
So my first call gets the data, and the user DOES exist, the hook is setting to true, however in my log it fails and the next API is ran. However if I do it a 2nd time, it is true...
What am I doing wrong.
const handleSubmit = async () => {
const data = await axios
.get(`URL`, {
})
.then((resp) => {
if (resp.data.user.name) {
setCheckUser(true);
console.log(resp.data.user.name);
}
return data;
})
.catch((err) => {
// Handle Error Here
console.error(err);
});
console.log(checkUser);
if (!checkUser) {
console.log('No User Found');
//Do Stuff//
}
};

I think the problem here is that setCheckUser(true) is an async operation, so there is no guarantee that the checkUser variable will turn to true right away.
Maybe you can solve this by using a useEffect block like this
//somewhere on the top of your file, below your useState statements
useEffect(()=> {
if (!checkUser) {
console.log('No User Found');
//Do Stuff//
}
}, [checkUser])
const handleSubmit = async () => {
const data = await axios
.get(`URL`, {
})
.then((resp) => {
if (resp.data.user.name) {
setCheckUser(true);
console.log(resp.data.user.name);
}
return data;
})
.catch((err) => {
// Handle Error Here
console.error(err);
});
};

Related

React Hook useEffect has missing dependencies: 'initializing', 'onAuthStateChanged', and 'user'. Either include them or remove the dependency array

Don't know what's the issue here.
If anyone know what's the issue here then please help me out.
I am trying to make anyonymous login.
Don't know what's the issue here.
If anyone know what's the issue here then please help me out.
I am trying to make anyonymous login.
const LoginManager = () => {
// Set an initializing state whilst Firebase connects
const [initializing, setInitializing] = useState(true);
const [user, setUser] = useGlobal('user');
// Handle user state changes
function onAuthStateChanged(user) {
setUser(user);
if (initializing) {
setInitializing(false);
}
}
useEffect(() => {
const subscriber = auth().onAuthStateChanged(onAuthStateChanged);
return subscriber; // unsubscribe on unmount
// eslint-disable-next-line react-hooks/exhaustive-deps
if (initializing) {
return null;
}
if (!user) {
return auth()
.signInAnonymously()
.then(() => {
console.log('User signed in anonymously');
})
.catch((error) => {
if (error.code === 'auth/operation-not-allowed') {
console.log('Enable anonymous in your firebase console.');
}
console.log(error);
});
} else {
console.log('User already signed in.');
}
}, []);
return null;
};

React Native UseEffect function is not working according to order

I want to get user's current location and set it into AsyncStorage a array. I will do it in the useEffect hook. But the problem is my functions are not working that according to given order. Here are my code
useEffect(() => {
getUserLocation();
setUserLocation();
check();
}, []);
/*Get User's Currunt Location*/
const getUserLocation = () => {
GetLocation.getCurrentPosition({
enableHighAccuracy: true,
timeout: 15000,
})
.then((location) => {
var lt = location.latitude;
var lg = location.longitude;
setlatitude(lt);
setlongitude(lg);
console.log("getUserLocation", lt, lg);
})
.catch((error) => {
const { code, message } = error;
console.warn(code, message);
});
};
/*Set User's Currunt Location to AsyncStorage*/
const setUserLocation = async () => {
try {
await AsyncStorage.setItem("user_location", JSON.stringify(userLocation));
console.log("setUserLocation", userLocation);
} catch (error) {
console.log("error setting user location");
}
};
const check = () => {
AsyncStorage.getItem("user_location", (err, result) => {
if (result !== null) {
console.log("check", result);
setlatitude(result.latitude);
setlongitude(result.longitude);
} else {
console.log("Data Not Found");
}
});
};
Whenever you use .then you are scheduling your code to run at some point in the future, when the promise has completed. So setUserLocation runs before the then of getUserLocation.
Also, it looks like your getUserLocation set react state, which won't be available until the next render. We use effects to manage this.
// Get the location on mount
useEffect(getUserLocation, []);
// Whenever the location updates, set it into storage
useEffect(() => setUserLocation().then(check), [latitude, longitude]);

Pass data from FormulateForm to a mapped action using Vuex

I'm currently using Vue Formulate to pass data, using #submit="login" on a FormulateForm, to a login(data) function.
Everything's working nicely as long as I keep the logic inside the component and I can send the data to my server using axios.
Thing is, I would like to put this login function in my Vuex store, as an action, but when I refer the #submit="login" from FormulateForm to the ...mapActions(["login"]) function, there is no data passed inside.
I logged data in the login(data) action, and I get this:
Response from console.log(data) in the vuex module
I could bind values from my inputs into the store and get them from there, but I'd prefer to keep this simple and use #submit.
Is it at all possible to do so?
Overview of the actual code that is working:
methods: {
login(data) {
axios
.post("http://localhost:3000/api/auth/login", data, {
withCredentials: true
})
.then(res => {
if (res.status === 200) {
this.setUserRole(res.data.isAdmin);
this.$router.push("/");
}
})
.catch(err => {
if (err.response.status === 404) {
// TODO: gestion d'erreur
} else if (err.response.status === 401) {
// TODO: gestion d'erreur
}
});
}
)
<FormulateForm #submit="login">
Overview of what I want, that is not working:
methods: {
...mapActions(["login"])
)
<FormulateForm #submit="login">
Inside Vuex module user.js:
const actions = {
login: data => {
console.log(data);
axios
.post("http://localhost:3000/api/auth/login", data, { withCredentials: true })
.then(res => {
if (res.status === 200) {
this.setUserRole(res.data.isAdmin);
this.$router.push("/");
}
})
.catch(err => {
if (err.response.status === 404) {
// TODO: gestion d'erreur
} else if (err.response.status === 401) {
// TODO: gestion d'erreur
}
});
}
};
As stated, the console.log(data)does not return my FormulateForm values as it does currently.
You did not dispatch the action login.
Do this
<FormulateForm #submit="handleLogin">
methods: {
...mapActions(["login"]), // here, you have mapped `this.login()` to this.$store.dispatch('login')
handleLogin(data) {
this.login(data); // pass data as a parameter
}
)
Then your vuex user.js store should be changed to
const actions = {
login: ({commit, state}, data) => { // it takes two arguments here
console.log(data);
}
};
For more on actions, please check the Vuex documentation
Do these things and it should work.

How to add navigation function inside async function?

I have created an async function that fetches data from api and turns red, whenever the icon is presses, however now I want just after the like function is completed it navigates to another page, however am not able to do it.
Kindly help,
Below is the way that I had tried,
onButtonPress = async(item) => {
console.log(item)
console.log(this.state.buttonColor,'hello')
if(!this.state.likedItemIds.includes(item._id)){
try {
const response = await fetch("some url"+item._id);
const resJson = await response.text();
this.setState(prevState => ({
likedItemIds: [...prevState.likedItemIds, item._id]
}))
console.log(resJson)
if(this.state.buttonColor!=='white'){
this.props.navigation.navigate('Wishlist')
}
}
catch (error) {
console.error(error);
}
}
Do tell me if anything else is required and kindly help.
setState is an asynchronous function that allows you to pass a callback as the second argument. So you can do your navigation in that callback, which will fire after setState is complete. This means you will navigate away from the page once the like is complete.
You can do the below:
onButtonPress = async(item) => {
console.log(item)
console.log(this.state.buttonColor,'hello')
if(!this.state.likedItemIds.includes(item._id)){
try {
const response = await fetch("some url"+item._id);
const resJson = await response.text();
this.setState(prevState => ({
likedItemIds: [...prevState.likedItemIds, item._id]
}), () => {
// Do whatever else you need to do here (validation, etc.)
this.props.navigation.navigate('Wishlist')
})
}
catch (error) {
console.error(error);
}
}

Return to request after refreshing tokens

I am trying to get refresh tokens working.
It works for the most part, but the problem is I'm not sure how to return to where the original call was before the access token needed refreshing.
It doesn't work the first time it refreshes, after that the token is refreshed and then it works ok again until it expires.
So the problem is I cant get it returning to where it started on the refresh
Here is an example from the component
created(){
axios.get("http://localhost:63861/api/sampledata/WeatherForecasts").then(response => {
console.log(response.data);
//**** DO STUFF WITH THE DATA. I WANT TO GET BACK HERE AFTER REFRESH
})
.catch(error => {
console.log(error);
});
I need to get back to the point where it can do stuff with the data once it has refreshed and reset the access tokens.
my interceptor:
import axios from "axios";
import store from "../store";
import Storage from "../services/storage";
import { REFRESH } from "../store/actions.type";
export default function execute() {
// Request
axios.interceptors.request.use(
config => {
var token = Storage.getAccessToken();
if (token) {
console.log("Bearer " + token);
config.headers["Authorization"] = "Bearer " + token;
}
return config;
},
error => {
return Promise.reject(error);
}
);
// Response
axios.interceptors.response.use(
response => {
return response;
},
error => {
console.log("Error need to refresh");
const originalRequest = error.config;
// token expired
if (error.response.status === 401) {
originalRequest._retry = true;
let tokenModel = {
accessToken: Storage.getAccessToken(),
client: "Web",
refreshToken: Storage.getRefreshToken()
};
var refreshPath = "auth/" + REFRESH;
store
.dispatch(refreshPath, { tokenModel })
.then(response => {
console.log(response);
return axios(originalRequest);
})
.catch(error => {
console.log(error);
// Logout
});
}
return Promise.reject(error);
}
);
}
You need to return your refresh promise.
return store
.dispatch(refreshPath, { tokenModel })
.then(response => {
console.log(response);
return axios(originalRequest);
})
.catch(error => {
console.log(error);
// Logout
});
What is happening now is you dispatch the action, then your return Promise.reject(error) is ran. By returning the refresh promise, you ensure axios waits for that chain to finish