I made a Storage.js file with some Utils function. In most case, I use it in this way:
async someFunction()=>{ let foo = await getOnDevice(someName)}
But the in my case, I have a problem with the syntax
import {AsyncStorage} from 'react-native'
export const saveOnDevice = async (name, data) => {
try {
if (data !== null && data !== undefined) {
await AsyncStorage.setItem(name, JSON.stringify(data));
}
} catch (error) {
console.log(error)
}
};
export const getOnDevice = async (name) => {
try {
const data = await AsyncStorage.getItem(name);
if (data !== null && data !== undefined) {
return data
}
} catch (error) {
console.log(error)
}
};
How can I use it without declaring an async function?
import {saveOnDevice} from '../../utils/Storage'
export function fetchUrlWithRedux(url) {
return (dispatch) => {
dispatch(fetchUrlRequest(url));
return fetchUrl(url, dispatch).then(([response, json]) => {
if (response.status === 200) {
saveOnDevice('url', json.data.host);
dispatch(fetchUrlSuccess(json))
}
else {
dispatch(fetchUrlError())
}
}).catch(() => dispatch(fetchUrlError()))
}
}
What is wrong with my code?
If you don't want to use async/await in your main file then you can use promise, like below.
saveOnDevice('url', json.data.host).then(() => {
dispatch(fetchUrlSuccess(json))
})
I think you need to add async before the anonymous function passed to .then(), and await before the call to saveOnDevice():
import {saveOnDevice} from '../../utils/Storage'
export function fetchUrlWithRedux(url) {
return (dispatch) => {
dispatch(fetchUrlRequest(url));
return fetchUrl(url, dispatch).then(async ([response, json]) => {
if (response.status === 200) {
await saveOnDevice('url', json.data.host);
dispatch(fetchUrlSuccess(json))
}
else {
dispatch(fetchUrlError())
}
}).catch(() => dispatch(fetchUrlError()))
}
}
Related
I'm trying to create a function that fetches data from The Guardian API but seem to be getting an error. The response returns this information:
And here is the code for the asynchronous function:
export async function getStaticProps() {
try {
const res = await fetch(
"https://content.guardianapis.com/search?api-key=xxxxxxxx&show-fields=thumbnail"
);
const { results } = await res.json();
const newsList = results.map((news) => {
return { ...news };
});
return {
props: { newsList },
};
} catch (err) {
console.error(err);
}
}
You almost got it. Only 1 thing you are missing is to return props even in the catch block
export async function getStaticProps() {
try {
const res = await fetch(
"https://content.guardianapis.com/search?api-key=xxxxxxxx&show-fields=thumbnail"
);
const { results } = await res.json();
const newsList = results.map((news) => {
return { ...news };
});
return {
props: { newsList },
};
} catch (err) {
console.error(err);
return {
notFound: true /// for rendering 404 page
};
}
}
I am new to react and I want to make an Axios.get() request based on a function parameter. This is what I tried.
const mentorName = (value) => {
try {
Axios.get(
`${BASE_URL}/api/v1/consultations/${value}`
).then(res => {
if (res.status !== 200 || res.data.status !== "success") {
console.log(res)
return
}
})
} catch (error) {
console.log(error)
}
}
But It didn't work as res was not printed in console. What is wrong in this?
The code that worked fine is:
const mentorName = (value) => {
try {
const res = Axios.get(
`${BASE_URL}/api/v1/consultations/${value}`
)
if (res.status !== 200 || res.data.status !== "success") {
console.log(res)
return
}
} catch (error) {
console.log(error)
}
}
The below code worked fine but returns information wrapped in a promise. How to access it now because res.data is not a valid property.
Can you try this with async/await.
import axios from 'axios';
const mentorName = async value => {
try {
const res = await axios.get(`${BASE_URL}/api/v1/consultations/${value}`);
console.log(res);
} catch (error) {
console.log(error);
}
};
In the console.log inside try block you can check for the api response.
const mentorName = (value) => {
try {
Axios.get(
`${BASE_URL}/api/v1/consultations/${value}`
).then(res => {
if (res.status !== 200 || res.data.status !== "success") {
console.log(res)
return
}
})
} catch (error) {
console.log(error)
}
}
above code doesn't print because of the if condition, it is likely that the status is going to be 200 most of the time and anything apart from 200 would drill down to catch block
the reason it is printing promise in below code is because, it is a promise waiting to be fulfilled and the comparison / condition you have put up is very much fine because res is a promise and res.status is undefined
const mentorName = (value) => {
try {
const res = Axios.get(
`${BASE_URL}/api/v1/consultations/${value}`
)
if (res.status !== 200 || res.data.status !== "success") {
console.log(res)
return
}
} catch (error) {
console.log(error)
}
}
tweak the code to include an else block and you can always see something printed in console
const mentorName = (value) => {
try {
Axios.get(
`${BASE_URL}/api/v1/consultations/${value}`
).then(res => {
if (res.status !== 200 || res.data.status !== "success") {
console.log(res)
return
} else {
console.log(res);
}
})
} catch (error) {
console.log(error)
}
}
I do not recommend using async/await due to one single and pressing reason, that the UI thread is put on hold until the async call is resolved. just to make it look like a synchronous call. stick on to the promise way.
I'm trying to remove the then statements from the following piece of code and then replace all the catches with try/catch statements. I'm having some issues knowing what to do with the then statements.
export class WelcomePageContribution implements IWorkbenchContribution {
constructor(
#IInstantiationService instantiationService: IInstantiationService,
#IConfigurationService configurationService: IConfigurationService,
#IEditorService editorService: IEditorService,
#IBackupFileService backupFileService: IBackupFileService,
#IFileService fileService: IFileService,
#IWorkspaceContextService contextService: IWorkspaceContextService,
#ILifecycleService lifecycleService: ILifecycleService,
#ICommandService private readonly commandService: ICommandService,
) {
const enabled = isWelcomePageEnabled(configurationService, contextService);
if (enabled && lifecycleService.startupKind !== StartupKind.ReloadedWindow) {
backupFileService.hasBackups().then(hasBackups => {
const activeEditor = editorService.activeEditor;
if (!activeEditor && !hasBackups) {
const openWithReadme = configurationService.getValue(configurationKey) === 'readme';
if (openWithReadme) {
return Promise.all(contextService.getWorkspace().folders.map(folder => {
const folderUri = folder.uri;
return fileService.resolve(folderUri)
.then(folder => {
const files = folder.children ? folder.children.map(child => child.name) : [];
const file = arrays.find(files.sort(), file => strings.startsWith(file.toLowerCase(), 'readme'));
if (file) {
return joinPath(folderUri, file);
}
return undefined;
}, onUnexpectedError);
})).then(arrays.coalesce)
.then<any>(readmes => {
if (!editorService.activeEditor) {
if (readmes.length) {
const isMarkDown = (readme: URI) => strings.endsWith(readme.path.toLowerCase(), '.md');
return Promise.all([
this.commandService.executeCommand('markdown.showPreview', null, readmes.filter(isMarkDown), { locked: true }),
editorService.openEditors(readmes.filter(readme => !isMarkDown(readme))
.map(readme => ({ resource: readme }))),
]);
} else {
return instantiationService.createInstance(WelcomePage).openEditor();
}
}
return undefined;
});
} else {
return instantiationService.createInstance(WelcomePage).openEditor();
}
}
return undefined;
}).then(undefined, onUnexpectedError);
}
}
}
so that the entire thing reads more like this..
const enabled = await isWelcomePageEnabled(configurationService, contextService);
if (enabled && lifecycleService.startupKind !== StartupKind.ReloadedWindow) {
const hasBackups = await backupFileService.hasBackups();
const activeEditor = editorService.activeEditor;
if (!activeEditor && !hasBackups) {
const openWithReadme = configurationService.getValue(configurationKey) === 'readme';
if (openWithReadme) {
...
It looks like you're on the right track with your second code block. then is called on a promise, so instead of using then you would await the function then was called on, save it to a variable, and then move the code that was in the callback to then below the await at the same indentation level. Whenever you await, you can wrap it in a try/catch and put what would have been in the catch callback inside of the catch block.
So for example
fetchData().then(data => {
console.log(data)
}).catch(err => {
console.error(err)
})
becomes
try {
const data = await fetchData()
console.log(data)
}
catch (err) {
console.error(err)
}
The complication in your example is that the code is in a class constructor, and those can't be async.
I want to use a value stored in the AsyncStorage in another function.
Here's my ValueHandler.js
import { AsyncStorage } from 'react-native';
export async function getSavedValue() {
try {
const val = await AsyncStorage.getItem('#MyStore:savedValue');
console.log("#getSavedValue", val);
return val;
} catch (error) {
console.log("#getSavedValue", error);
}
return null;
}
I made the above function getSavedValue() to get the value of the savedValue stored in the AsyncStorage.
import {getSavedValue} from '../lib/ValueHandler';
import Api from '../lib/Api';
export function fetchData() {
return(dispatch, getState) => {
var params = [
'client_id=1234567890',
];
console.log("#getSavedValue()", getSavedValue());
if(getSavedValue() != null) {
params = [
...params,
'savedValue='+getSavedValue()
];
}
params = params.join('&');
console.log(params);
return Api.get(`/posts/5132?${params}`).then(resp => {
console.log(resp.posts);
dispatch(setFetchedPosts({ post: resp.posts }));
}).catch( (ex) => {
console.log(ex);
});
}
}
How do I achieve this? I really wanted a simple method to save a value in the local storage and retrieve it simply when I need to make an API call.
Anyone got any suggestions or solutions to this?
Try this:
Adding async to return (dispatch, getState) => { so you can await in it
import {getSavedValue} from '../lib/ValueHandler';
import Api from '../lib/Api';
export function fetchData() {
return async (dispatch, getState) => {
let params = [
'client_id=1234567890',
];
const val = await getSavedValue();
if (val != null) {
params = [...params, 'savedValue='+val];
// why not
// params.push(`savedValue=${val}`);
//
}
params = params.join('&');
return Api.get(`/posts/5132?${params}`))
.then(resp => {
dispatch(setFetchedPosts({ post: resp.posts }));
})
.catch( (ex) => {
console.log(ex);
});
};
}
You can do something like this:
import { AsyncStorage } from 'react-native';
export async function getSavedValue() {
return new Promise ((resolve, reject) => {
try {
const val = await AsyncStorage.getItem('#MyStore:savedValue');
console.log("#getSavedValue", val);
resolve(val);
}catch (error) {
console.log("#getSavedValue", error);
reject(error)
}
})
}
import {getSavedValue} from '../lib/ValueHandler';
import Api from '../lib/Api';
export function fetchData() {
return async (dispatch, getState) => {
var params = [
'client_id=1234567890',
];
console.log("#getSavedValue()", getSavedValue());
if(getSavedValue() != null) {
params = [
...params,
'savedValue='+ await getSavedValue()
];
}
params = params.join('&');
console.log(params);
return Api.get(`/posts/5132?${params}`).then(resp => {
console.log(resp.posts);
dispatch(setFetchedPosts({ post: resp.posts }));
}).catch( (ex) => {
console.log(ex);
});
}
}
The first chunk as an action creator below works as is with thunk, but I want to also apply the 2nd chunk, which is a promise middleware. How do I tweak it so that it can dispatch 2 actions?
export const fetchPokemon = function (pokemonName) {
return function (dispatch) {
dispatch({type: 'REQUESTING'})
const requestURL = `http://pokeapi.co/api/v2/pokemon/${pokemonName}/`
return fetch(requestURL)
.then(function (response) {
return response.json()
})
.then(function (data) {
dispatch(receivePokemon(formatPokemonData(data)))
dispatch(fetchPokemonDescription(pokemonName))
})
}
}
middleware
const fetchPromiseMiddleware = store => next => action => {
if (typeof action.then !== 'function') {
return next(action)
}
return Promise.resolve(action).then(function (res) {
if (res.status >= 400) {
throw new Error("Bad response from server")
}
return res.json()
}).then(store.dispatch)
}
I've tried the below but get an error:
store.js:33 Uncaught (in promise) TypeError: (0 ,
_actionCreators.receivePokemon) is not a function
const fetchPromiseMiddleware = store => next => action => {
if (typeof action.then !== 'function') {
return next(action)
}
return Promise.resolve(action).then(function (res) {
if (res.status >= 400) {
throw new Error("Bad response from server")
}
return res.json()
}).then(function (data) {
return store.dispatch(receivePokemon(formatPokemonData(data)))
}).then(function (data) {
return store.dispatch(fetchPokemonDescription(data.name))
})
}
there's not enough code in your question, but it seems when you call receivePokemon(formatPokemonData(data)) in the code you show, receivePokemon isn't a function, now you need to check where is that defined, it probably isn't.