I am trying to do a axios get call to my backend server with path variable and save the response data to the store. Unfortunately it only works for the get call with no path variables. still I can also log the response in the console, but I am unable to dispatch the response.data to the store
fetchByCardNumber: (CardNumber) => axios.get(baseURL+'loyalty/loyaltyCustomer/card/'+ CardNumber)
export const fetchByCardNumber = (CardNumber) => dispatch => {
LoyaltyAPI().fetchByCardNumber(CardNumber)
.then(response => {
if (response.status !== 200){
dispatch(Customer(null))
} else {
dispatch(Customer(response.data))
}
}).catch(error => {
return error;
})
}
But wherever I have used the url without pathVaribale in axios get call it works.
Eg : fetchCards: () => axios.get(baseURL+'loyalty/loyaltyCard/all')
While using the above URL I can dispatch the response to the store and get it.
//use it like that without curly braces between {cardNumber}
fetchByCardNumber: (CardNumber) => axios.get(baseURL+'loyalty/loyaltyCustomer/card/'+ CardNumber)
export const fetchByCardNumber = (CardNumber) => dispatch => {
LoyaltyAPI().fetchByCardNumber(CardNumber)
.then(response => {
if (response.status !== 200){
dispatch(Customer(null))
} else {
dispatch(Customer(response.data))
}
}).catch(error => {
return error;
})
}
The issue was with the way on dispatching the response to the store. The below code worked.
export const fetchByCardNumber = (CardNumber) => dispatch => {
LoyaltyAPI().fetchByCardNumber(CardNumber)
.then(response => {
if (response.status !== 200){
store.dispatch(SelectedCustomer(null))
} else {
store.dispatch(SelectedCustomer(response.data))
}
}).catch(error => {
return error;
})
}
Related
I chose to start learning API handling with POKEAPI. I am at a step where I need to get the flavor_text of each pokemon (the description let's say) but I can't for some reason.
Here is the JSON structure for one specific pokemon: https://pokeapi.co/api/v2/pokemon-species/bulbasaur.
And here is my useEffect trying to get it. The line fetching the habitat works and displays on my website so I guess my issue comes from my map in setDescription but I can't be sure.
export default function Card({ pokemon }, { key }) {
const src = url + `${pokemon.id}` + ".png";
const [habitat, setHabitat] = useState(null);
const [descriptions, setDescriptions] = useState([]);
useEffect(() => {
const controller = new AbortController();
axios
.get(url2 + `${pokemon.name}`, { signal: controller.signal })
.then((res) => setHabitat(res.data.habitat.name))
.then((res) =>
setDescriptions(
res.data.flavor_text_entries.map((ob) => ob.flavor_text)
)
)
.catch((err) => {
if (axios.isCancel(err)) {
} else {
console.log("warning your useEffect is behaving");
}
});
return () => {
// cancel the request before component unmounts
controller.abort();
};
}, [pokemon]);
I tried console logging descriptions or descriptions[0] but that doesn't work.
Since you only setting up the state from those data and it doesn't looks like the second result need to wait the result from the first to perform you can do both on the same response/promise :
useEffect(() => {
const controller = new AbortController();
axios
.get(url2 + `${pokemon.name}`, { signal: controller.signal })
.then((res) => {
setHabitat(res.data.habitat.name))
const flavorTextEntrieList = res.data.flavor_text_entries;
setDescriptions(flavorTextEntrieList.map((ob) => ob.flavor_text))
})
.catch((err) => {
if (axios.isCancel(err)) {
} else {
console.log("warning your useEffect is behaving");
}
});
return () => {
// cancel the request before component unmounts
controller.abort();
};
}, [pokemon]);
Each then need to return something to be handled in next chainable then. Replace .then((res) => setHabitat(res.data.habitat.name)) with .then((res) => { setHabitat(res.data.habitat.name); return res; })
I am using React, Formik and Axios however when I make the axios calls, Axios seems to be making two api calls one after the other in succession.
What a I doing wrong? How can I avoid this? Any help much appreciated.
Added code sandbox link
https://codesandbox.io/embed/clever-einstein-e9609?fontsize=14&hidenavigation=1&theme=dark
const handleFormSubmit = (values, {setSubmitting}) => {
const {artifact, match_strategy, merge_strategy} = values;
setIsDisabled(true);
setUploadArtifactError(<span className="text-success"><b>Processing...</b></span>)
getImageAsBytes(values.artifact)
.then(data => {
setSubmitting(false)
postArtifact(data, artifact, match_strategy, merge_strategy);
})
.catch(error => {
console.log('Convert as bytes error ', error);
setIsDisabled(false);
});
}
const postArtifact = (payload, file, match_strategy, merge_strategy) => {
setUploadArtifactError(<span className="text-success"><b>Uploading ...</b></span>)
axios.post(`${baseUrl}artifact/load?name=${file.name}`, payload)
.then(res => {
const {_id, blob_url } = res.data.data;
const payload = {
"ref": `${file.name}_${new Date().getMilliseconds()}`,
"config": {
"match_strategy": match_strategy,
"merge_strategy": merge_strategy,
"artifact_ids" : [_id]
}
}
// console.log('artifact upload res ', _id, blob_url)
if(res.status === 200) {
postLoadSites(payload);
}
})
.catch(error => {
console.log('artifact upload error ', error)
setUploadArtifactError(<span className="text-warning"><b>Unable to upload at this time, (try different Match or Merge Strategy) or please try again later</b></span>);
setIsDisabled(false);
})
}
const postLoadSites = (payload) => {
axios.post(`${baseUrl}load/sites`, payload)
.then(res => {
if(res.status === 200) {
setUploadSitesError(<span className="text-success"><b>Uploaded Sites Successfully!</b></span>);
setUploadArtifactError('');
setIsDisabled(false);
handleMultiUploadCallback();
}
})
.catch(error => {
console.log("multi site upload error ", error);
setUploadSitesError(<span className="text-warning"><b>Unable to upload at this time, (try different Match or Merge Strategy) or please try again later</b></span>);
setIsDisabled(false)
})
}
This is how the network looks
First, apologize for my english.
I'm trying to make a request with redux-thunk.... I dont understan it well.
My idea is make a request using axios but method return undefined before return value of request.
I dont know if I'm passing dispatch well.
Can you help me please? What am I doing wrong???
This is how use dispatch in my component:
....
const mapDispatchToProps = dispatch => {
return {
createCustomersGeoJSON: () => dispatch(createCustomersGeoJSON()),
getAdvicesData: hierarchy => dispatch(getAdvicesData(hierarchy)),
getSocialNetworkData: () => dispatch(getSocialNetworkData()),
dispatch,
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(injectIntl(CustomersWidget));
In actions I do this:
export const getSocialNetworkData = () => {
return dispatch => {
dispatch({
type: GET_SOCIAL_NETWORK_DATA,
payload: fetchSocialNetworkData(),
});
};
};
And this is the code of fetchSocialNetworkData function:
axios
.get(`http://localhost:5000/socialRoute`)
.then(data => {
let response = Object.assign({}, data);
if (
response &&
response.data &&
response.data.tweets &&
Array.isArray(response.data.tweets)
) {
console.log("data.tweets: ", response.data.tweets);
return response.data.tweets;
}
return [];
})
.catch(error => {
console.log("Error gettin data from socialRoute: ", error);
});
It's because you think you're returning the response but what you're actually returning is nothing because you've handled the result of the promise in a .then chain.
You have two options:
Return a promise and resolve it in the .then:
function fetchSocialNetworkData() {
return new Promise((resolve) => {
axios
.get(`http://localhost:5000/socialRoute`)
.then(data => {
let response = Object.assign({}, data);
if (
response &&
response.data &&
response.data.tweets &&
Array.isArray(response.data.tweets)
) {
console.log("data.tweets: ", response.data.tweets);
resolve(response.data.tweets);
}
resolve([]);
})
})
}
OR
Use async/await (the modern way)
async function fetchSocialNetworkData() {
const data = await axios.get(`http://localhost:5000/socialRoute`);
let response = Object.assign({}, data);
if (
response &&
response.data &&
response.data.tweets &&
Array.isArray(response.data.tweets)
) {
console.log("data.tweets: ", response.data.tweets);
return response.data.tweets;
}
return [];
}
Both of these are the same thing under the hood. IE they're both different ways of writing a promise.
Now. in your thunk, you're still just calling that function, which means you're going to get the unresolved promise rather than the result of that promise. So the thunk becomes:
export const getSocialNetworkData = () => {
return async (dispatch) => {
dispatch({
type: GET_SOCIAL_NETWORK_DATA,
payload: await fetchSocialNetworkData(),
});
};
};
The thing to take away from this is that you can get far without understanding promises but that lack of understanding will always be a ceiling for your JS skills.
I have functions
export function configureInterceptors(store) {
axios.interceptors.response.use(
response => response,
error => {
if (error.response && error.response.data) {
if (error.response.status === 401 && err.config) {
const originalRequest = error.config;
originalRequest._retry = true;
store.dispatch(jwtRefresh(originalRequest))
}
throw error;
}
}
);
}
export const jwtRefresh = (originalRequest) => dispatch => {
dispatch(jwtRefreshBegins());
axios
.post('auth/jwt/refresh/', {
refresh: window.localStorage.getItem('refresh')
})
.then(response => {
window.localStorage.setItem('jwt', response.data.access);
originalRequest.headers.Authorization = `JWT ${response.data.access}`;
return axios(originalRequest)
})
.catch(err => {
window.localStorage.removeItem('token');
window.localStorage.removeItem('jwt');
})
};
But all of my requests are in redux function. How can I make redux function again if refresh token was success? I must use redux function, because it change redux state.
I am trying to get thumbnail path and storing to a variable to be used, But I am getting undefined
getThumbnail(filePath){
let thumbnailURL = RNThumbnail.get(filePath)
.then((response) => response.path)
.then((responseData) => {
console.warn(responseData);
return responseData;
}).catch(error => console.warn(error));
alert(thumbnailURL);
//return thumbnailURL;
}
.then doesn't work like that, it won't return a value. You could do:
let thumbnailURL;
RNThumbnail.get(filePath)
.then((response) => response.path)
.then((responseData) => {
thumbnailURL = responseData;
alert(thumbnailURL);
}).catch(error => console.warn(error));
but you have to continue computation inside the second then call because the value is only going to be reliable there
You're better off using async/await, just refactor your code to this:
async function getThumbnail(filePath){
try {
let thumbnailURL = await RNThumbnail.get(filePath)
alert(thumbnailURL)
} catch(err) {
console.warn(err)
}
read more about async / await
For React app, most likely you will want to set the response as state:
state = {
thumbnailURL: ''
}
getThumbnail = (filePath) => {
RNThumbnail.get(filePath)
.then(response => response.path)
.then(responseData => {
this.setState({
thumbnailURL: responseData
})
})
.catch(error => console.warn(error))
}
render() {
return (
<img src={this.state.thumbnailURL} />
)
}
You will need arrow function on getThumbnail for lexical binding so that you can access this.setState().
Edit:
You can't actually make getThumbnail() return thumbnailURL value right away. getThumbnail() can however return the promise, and you resolve it at the place where you want access to thumbnailURL:
getThumbnail = filePath => {
return RNThumbnail.get(filePath)
.then(response => response.path)
.then(responseData => responseData)
.catch(error => console.warn(error))
}
IWannaAccessThumbnailURLHere = () => {
this.getThumbnail('....')
.then(thumbnailURL => {
// do things with thumbnailURL
})
}
Or, use setState, re-render then you can access this.state.thumbnailURL in the next render-cycle.