AsyncStorage not getting into then() method in react native - react-native

It seems like the async await doesn't work in react native. When I run the code below, it just logs 'here", not the value.
class CompanyDetails extends Component {
...
componentDidMount = async () => {
await this.getCompDetailsData();
}
getCompDetailsData = async () => {
console.log('here');
await AsyncStorage.getItem('CompanyID')
.then((value) => {
console.log(value);
const compID = JSON.parse(value);
console.log(compID);
this.props.getCompDetails(propID);
});
};
...
Does anyone know why it is happening?
Thanks

Did you had 'CompanyID' stored somewhere before because if you did not store it before then it will go to the catch part which is not implemented in your case
getCompDetailsData = async () => {
console.log('here');
await AsyncStorage.getItem('CompanyID')
.then((value) => {
console.log(value);
const compID = JSON.parse(value);
console.log(compID);
this.props.getCompDetails(propID);
}).catch(error => {
console.log("CompanyID is not defined yet");
});
};

You may not have a saved value in that name "CompanyID"

Related

How to use redux on a global functions

Iam currently working with a react-native project and wanted to use redux now what i want is that a global function that handles all firebase fetch data here is my globla function
connectFunctions.js
export const pullDataFromFirebaseSubCollection = async (collectionName, docId, subCollection, reducerName,) => {
const q = query(collection(db, collectionName,docId,subCollection));
const querySnapshot = await getDocs(q);
const documents = querySnapshot.docs.map((doc) => ({ key_id: doc.id, ...doc.data() }));
var redData = {
reducerName:reducerName,
data:documents
}
store.dispatch(middlewareDispatch(redData))//tried it inside the function does not work
return documents;
}
so on my App.js i imported then connectFunction.js and use pullDataFromFirebaseSubCollection
useEffect(()=>{
let isMounted = true; // note mutable flag
onAuthStateChanged(auth, (user) => {
if (user) {
console.log("user appjs", user);
dispatch(updateLoginStatus(true));
pullDataFromFirebaseSubCollection("Students","1","playlist","playlist").then((data)=>{
}).catch((err)=>{
console.log("logged error", err);
})
} else {
dispatch(updateLoginStatus(false))
}
_handleFinishLoading()
})
return () => { isMounted = false }
},[])
so on my library.js
i called store.getState().reducer.playlist the result is empty

Jest does not continue after async method

I have an async method triggered by a click event where I make a call to an API and then process the response, like this:
async confirmName () {
const {name, description} = this.form;
const [data, error] = await Pipelines.createPipeline({name, description});
if (error) {
console.error(error);
this.serviceError = true;
return false;
}
this.idPipelineCreated = data.pipeline_id;
return true;
}
The test looks like this:
test("API success", async () => {
const ConfirmNameBtn = wrapper.find(".form__submit-name");
await ConfirmNameBtn.vm.$emit("click");
const pipelinesApi = new Pipelines();
jest.spyOn(pipelinesApi, "createPipeline").mockResolvedValue({pipeline_id: 100});
const {name, description} = wrapper.vm.form;
pipelinesApi.createPipeline().then(data => {
expect(wrapper.vm.pipelineNameServiceError).toBe(false);
wrapper.setData({
idPipelineCreated: data.pipeline_id
});
expect(wrapper.vm.idPipelineCreated).toBe(data.pipeline_id)
}).catch(() => {})
})
A basic class mock:
export default class Pipelines {
constructor () {}
createPipeline () {}
}
I'm testing a success API call and I mock the API call returning a resolved promised. The problem is the coverage only covers the first two lines of the method, not the part where I assign the response of the API call. Is this the correct approach?
Edit:
Screenshot of coverage report:
Don't mix up await and then/catch. Prefer using await unless you have very special cases (see this answer):
test("API success", async () => {
const ConfirmNameBtn = wrapper.find(".form__submit-name");
await ConfirmNameBtn.vm.$emit("click");
const pipelinesApi = new Pipelines();
jest.spyOn(pipelinesApi, "createPipeline").mockResolvedValue({pipeline_id: 100});
const {name, description} = wrapper.vm.form;
const data = await pipelinesApi.createPipeline();
expect(wrapper.vm.pipelineNameServiceError).toBe(false);
wrapper.setData({
idPipelineCreated: data.pipeline_id
});
expect(wrapper.vm.idPipelineCreated).toBe(data.pipeline_id)
expect(wrapper.vm.serviceError).toBe(false);
})

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]);

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);
}
}

undefined is not an object this.props.auth from redux

I am trying to navigate to a different screen on success of my authentication function. This is the approach I'm taking, but I am getting undefined is not an object when I try to use .then()
This is my code
login = () => {
const {username, password} = this.state
this.props.authentication(username, password).then(res => {
})
}
const mapDispatchToProps = dispatch => {
return {
authentication: (username, password) =>
dispatch(authenticationLoginEmail(username, password)),
};
};
This my redux code
export const authenticationLoginEmail = (username, password) => {
return dispatch => {
dispatch(authLoginEmailStart())
axios.post('url',{username, password})
.then(res=>{
console.log(res.data.idusers,'ID USERS');
...
dispatch(authLoginEmailSuccess(idusers, token))
return res
})
.catch(err=>{
dispatch(authLoginEmailfail(err))
console.log(err);
})
}
}
Error
undefined is not an object (evaluating '_this.props.authentication(username, password).then')
thanks for helping
i think you should not use it like promise
this.props.authentication(username, password).then(res => { })
if you want to a response you have to just call this in your code
this.props.authentication(username, password);
And if your fetch finished you will send your success or error into redux state
dispatch(authLoginEmailSuccess(idusers, token))
or
dispatch(authLoginEmailfail(err))
and you can save your state in reducer and then get it into your component in mapStateToProps