React SWR fetch undefined - reactjs

Hi I am trying to fetch data from API with apiKey.
But get undefined
const fetchTest = (url, key) => {
fetch(url, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'X-AUTH-TOKEN': key
}
}).then((response) => response.json())
.then((responseData)=> responseData);
};
const { data, error } = useSWR(['api/link','apiKey'], (url, key) => fetchTest(url, key));
If I try to console.log(data) always get undefined.
But strange thing if I will use console.log() inside of fetchTest() right after
.then((responseData)=> responseData) and will do something like .then((response) => response.json()).then((responseData)= console.log(responseData))
I get exactly what I need. Am I doing something wrong ?

You are not returning the fetch.
you should put the return statement before the fetch or remove the curly bracers like this => fetch

Related

React-query mutation isError not setting true on failed POST

I am using the following fetch post request to create an item in my DB. I am trying to use react-query to detect the error thrown by the request.
export function createItem(id, body, token) {
fetch(`${API_URL}/${id}/items`, {
method: 'post',
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
body: JSON.stringify(body)
})
.then(res => {
if (res.ok) {
return res.json()
}
console.log(res.status)
throw new Error("Error creating review")
})
.catch((err) => console.log(err))
}
I have the mutation set like so:
const mutation = useMutation(() => {
return createItem(props.item.id, item, token)
})
And its called with:
<Button disabled={!valid} onPress={() => mutation.mutate()}>
Submit
</Button>
I use this logic to display the error:
{
mutation.isError && <Text>{mutation.error.message}</Text>
}
I see the createItem function errors with a 400 status code which is what I expect but react-query does not set isError to true. Instead isSuccess is true. Am I handling the error wrong some how?
From the react query docs, they return a promise to the mutation, so try to change your function createItem to the following:
export function createItem(id, body, token) {
// return the fetch as a promise
return fetch(`${API_URL}/${id}/items`, {
method: 'post',
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
body: JSON.stringify(body)
})
// remove then and catch here
The problem is that you are catching the error inside the mutation function. React Query requires to you to return a resolved or rejected promise from your function.
Promise.catch also returns a Promise. If you don't return anything, it will be a Promise that returns undefined. But that is still a resolved Promise that will be passed to React Query.
So, in short: Don't catch inside the function. Use one of the callbacks that react-query provides for error logging:
export function createItem(id, body, token) {
fetch(`${API_URL}/${id}/items`, {
method: 'post',
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
body: JSON.stringify(body)
})
.then(res => {
if (res.ok) {
return res.json()
}
console.log(res.status)
throw new Error("Error creating review")
})
}
const mutation = useMutation(
() => {
return createItem(props.item.id, item, token)
},
{
onError: (error) => console.log(error)
}
)

React: Can't pass an id to an endpoint in order to display an image

I'm quite new to react and have an issue that i'm not sure whats wrong.
I have one external api with an endpoint that contains articles and another endpoint to get the images thats connected with the articles. I want to display the articles and the images together, but I can't get the images to show.
The flow is as follows:
First I find the article with the article api endpoint and the article id. And it looks like this:
const { itemId } = useParams()
const [article, setArticle] = useState([])
const [articleImg, setArticleImg] = useState('')
const [fileId, setFileId] = useState('')
useEffect(() => {
fetch(`https://api.fortnox.se/3/articles/${itemId}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'Access-Token': accessToken,
'Client-Secret': clientSecret
}
})
.then((res) => res.json())
.then((data) => {
console.log(data)
setArticle(data.Article)
console.log(data)
})
}, [itemId])
In order to get the image to that article I have to find a FileId by searching the article number against ArticleFileConnections endpoint:
(Documentation)
useEffect(() => {
fetch(`https://api.fortnox.se/3/articlefileconnections/?articlenumber=${itemId}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'Access-Token': accessToken,
'Client-Secret': clientSecret
}
})
.then((res) => res.json())
.then((data) => {
setFileId(data.ArticleFileConnections[0].FileId)
console.log(data.ArticleFileConnections[0].FileId) // Prints an id-number in the console
})
}, [])
When I have the FileId I use it with another endpoint called Archive in order to get the image. Documentation That fetch looks like this:
useEffect(() => {
fetch(`https://api.fortnox.se/3/archive/${fileId}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'Access-Token': accessToken,
'Client-Secret': clientSecret
}
})
.then((res) => res.json())
.then((data) => {
setArticleImg(data)
console.log(data) // Prints an object thats a folder structure with an empty array
})
}, [])
I tried to change the ${fileid} to the actual id-number in the archive endpoint like this
https://api.fortnox.se/3/archive/8c05c536-c110-402d-82da-60f25f6b0e1c Then I get this error message in the console:
Uncaught (in promise) SyntaxError: Unexpected token � in JSON at position 0
But I don't get that error if I pass the ${fileid} in the endpoint https://api.fortnox.se/3/archive/${fileid} Although when I console.log the state fileId that I pass in it prints the fileId-number.
So what I expect is that the fileId-state that I use in the archive endpoint should display an image by writing this code.
<div>
<img src={articleImg} alt="product" />
</div>
I hope all this is understandable and I hope someone can help me with what i'm doing wrong.
Thank you.
Note: It all works in postman. When I try the endpoints like the flow above it shows the image with this endpoint https://api.fortnox.se/3/archive/8c05c536-c110-402d-82da-60f25f6b0e1c
Your useEffect for fetching the fileId is behaving as a componentDidMount. What you want instead is a componentDidUpdate behavior, which you can do by
useEffect(() => {
fetch(`https://api.fortnox.se/3/archive/${fileId}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'Access-Token': accessToken,
'Client-Secret': clientSecret
}
})
.then((res) => res.json())
.then((data) => {
setArticleImg(data)
console.log(data) // Prints an object thats a folder structure with an empty array
})
}, [fileId]) // Notice the change here. It ensures that the useEffect is called every time the fileId is updated.

React: res.json() data is undefined

I'm having issues with getting data from my fetch API. It was working previously when I had "test" inside of a class. Now that it's inside of a function, I get "undefined" when I try to console.log(data). (Note, the API call is working on the server. console.log(res.json()) returns a data. I'm LOST.
const test = () => {
fetch('/api/test/', {
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
//make sure to serialize your JSON body
body: JSON.stringify({zip: val})
})
.then(res => { res.json()}) //THIS RETURNS OK
.then(data => {console.log({data})}) //THIS IS WHERE I HAVE PROBLEMS
}
EDIT:
I also tried
.then(data=> {console.log(data)})
and
.then(data => {console.log([data])})
is there something I'm missing?
Arrow_functions
You should return res.json() to work successfully;
.then(res => { return res.json()})
or
.then(res => res.json())

Put call in reactjs

This is my service method , where I need to do the put call to an API by passing an id. Is this the correct way, bcoz I am not able to hit my .put URL
ENDPOINTS = {
SAMPLE: "/sample",
};
This is my service method:
updateApi(): Promise<any> {
const config = {
headers: {
accept: "application/json",
"Content-Type": "application/json",
},
};
const data = {
// data
};
const id = sample.id;
return http
.put(`${this.ENDPOINTS.SAMPLE}${id}`, data, config)
.then((response) => {
return response.data;
})
.catch((error) => {
throw error;
});
}
I believe your issue is the line const {id} = sample.id;
This should instead be: const { id } = sample; or the equivalent const id = sample.id.
In addition, your API endpoint is missing a trailing /, so you should include it in your .put() call.
Example: ${this.ENDPOINTS.SAMPLE}/${id}
Not sure if you have any reason for using http here but if you are flexible then try fetch API available in react.
const requestOptions = {
method: 'PUT',
headers: {
accept: "application/json",
"Content-Type": "application/json",
},
body: data
};
fetch(`${ENDPOINTS.SAMPLE}/${sample.id}`, requestOptions)
.then(response => response.json())
.then(data => this.setState({ // update data here }));
If you are directly making call to API in your component then above code can be placed inside componentDidMount.
Let me know if you face any issue!

Stripe checkout error

I am trying to implement stripe checkout to me store and I get an error saying:
Here is my code:
onToken = (token) => {
fetch('/save-stripe-token', {
method: 'POST',
body: JSON.stringify(token),
}).then(response => {
response.json().then(data => {
alert(`We are in business, ${data.email}`);
});
});
}
Looks like there was an error parsing the object into json. It would be helpful to know what you are calling onToken with.
Make sure to set Content-Type and Accept headers with application/json when making your request:
fetch('...', {
// ...
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
// ...
})
Make sure to always add a catch block to deal with errors. Also I suggest you return the response.json() instead of dealing with right away in the same then block (this is an anti-pattern that does not help in alleviating callback hell).
fetch(...)
.then(response => {
return response.json();
})
.then(data => {
alert(`We are in business, ${data.email}`);
})
.catch(error => {
// Handle the error here in some way
console.log(error);
});

Resources