Sveltekit Actions returns garbled json - sveltekit

json returned from a Sveltekit actions is garbled. I would expect something like this:
{ foo: bar, foo2: bar2 }
But instead I get this:
Array({ foo: 1, foo2: 2 }, bar, bar2)
Which is even more annoying with nested data.
This is how I send it:
const response = await fetch('/api/fetch', {
method: 'POST'
}).then((res) => {
res.json().then((r) => {
console.log(JSON.parse(r.data))
})
})
This is api/fetch/+page.server.js
export const actions = {
default: async ({ request }) => {
const response = await fetch(
'https://exterual-url-that-returns-json', {
method: 'GET'
}
)
return await response.json()
}
}
I have the same problem even if the json object is not fetched from an external url, i.e. return { foo: bar, foo2: bar2 }

The JSON is not garbled but serialized via devalue which has fewer limitations than plain JSON.stringify, e.g. it retains Date, Set and Map objects.
The JSON is supposed to be consumed by SvelteKit code which should automatically convert it correctly. Actions are supposed to be used with <form> elements and the result is passed to the page in a form property; to process the request asynchronously, use the enhance action.
If you for some reason have to process the data manually, use the deserialize from $app/forms.

Related

Axios API call returns a 404 on page render, but still returns api objects in terminal

I am using axios to make an api call to an api found on Apihub for a next JS app.
here is the code for the function to make the call to provide a list of property JSON objects.
export const baseUrl = "https://zillow56.p.rapidapi.com"
export const fetchApiListsingsCustom = async (url) => {
const { data } = await axios.get((url), {
method: 'GET',
headers: {
'X-RapidAPI-Key': '328713ab01msh862a3ad609011efp17e6b4jsn0e7112d5ee9a',
'X-RapidAPI-Host': 'zillow56.p.rapidapi.com'
}
});
data.then((res) => {
console.log(res);
})
.catch((error) => {
console.error(error);
});
return data.json();
}
When rendering the page I'm attempting to inject the response's data to dynamically create a list of apartment listings.
I'm trying to use getServerSideProps so that the data is already available by the time a user requests the page. After fetching the data, I want to also print them in the terminal to validate it's success.
export default function Home({ propertiesCustomdata })
export async function getServerSideProps() {
const propertiesCustom = await fetchApiListsingsCustom(`${baseUrl}`)
const propertiesCustomdata = propertiesCustom.json()
return {
props: {
propertiesCustomdata
}
}
}
The problem is, I seem to be getting a 404 error from the axios call, before the page gets a chance to load. When I access this I get a 404 error but I also manage to receive some contents of the call the API was to make.
My apologies if this is unclear, but this is all I know to report on this so far.
Studying async and await, fetch, and axios. Very confusing.

React: Can't figure out how to use fetched API response

I'm working with a nice chatbot program for React someone wrote, and the thing is, you can actually bind the bot's responses to function calls like this:
render() {
const { classes } = this.props;
return (
<ChatBot
steps={[
{
...
{
id: '3',
message: ({ previousValue, steps }) => {
this.askAnswer(previousValue)
},
end: true,
},
]}
/>
);
Where message is the answer of the bot that it calculates based on the previousValue and askAnswer is a custom function you'd write. I'm using an API that inputs the previousValue to a GPT model, and I want to print the response of this API.
However, I just can't wrap my head around how I could pass the response of the API to the message. I'm trying this:
constructor(props) {
super(props);
this.state = { response: " " };
}
...
askAnswer(question) {
var jsonData = { "lastConversations": [question] }
fetch('http://my_ip:80/query', {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(jsonData)
}).then(response => response.json())
.then(data => { this.setState({ response: data["botResponse"] }) });
return (this.state.response)
}
I've been struggling with this for the past 2-3 hours now.
I've tried a couple of combinations, and nothing seems to work:
If I do as seen above, it seems like this.state.response just won't get
updated (logging data["botResponse"] shows there is a correct
reply, so the API part works and I get the correct response).
If I try async-await for askAnswer and the fetch call, then I can
only return a Promise, which is then incompatible as input for the
ChatBot message.
If I do not await for the fetch to complete, then
this.state.response just stays the default " ".
If I return the correct data["botResponse"] from within the second .then after the fetch, nothing happens.
How am I supposed to get the API result JSON's data["botResponse"] text field out of the fetch scope so that I can pass it to message as a text? Or, how can I get a non-Promise string return after an await (AFAIK this is not possible)?
Thank you!
In your last 2 line
.then(data => { this.setState({ response: data["botResponse"] }) });
return (this.state.response)
You are updating the state and trying to read and return the value in the same function which I think will never work due to async behaviour of state. (this is why your this.state.response in the return statement is the previous value, not the updated state value).
I'm not sure but you can write a callback on this.setState and return from there, the callback will read the updated state value and you can return the new state.

Redux toolkit RTK query mutation not getting returning data

Hi I recently learned the new react toolkit with the rtk query tool, and I am trying to put in a login system together using the createApi from the rtk package.
After giving it a test on the login button pressed, I see the network request going through without any issue(status code 200), and I get a response object providing user, token, however, when I try to get the returning data using useLoginMutation I get an undefined value.
below is the code for my endpoint which is injected in a base api:
export const apiLogin = theiaBaseApi.injectEndpoints({
endpoints: (build) => ({
loginUser: build.mutation<UserReadonly, loginValuesType | string>({
query: (values: loginValuesType, redirect?: string) => {
const { username, password } = values;
const header = gettingSomeHeaderHere
return {
url: "login",
method: "GET",
headers,
crossDomain: true,
responseType: "json",
};
},
}),
}),
});
export const { useLoginUserMutation } = apiLogin
then inside my React component I destructure the mutation result such like below:
const [login, {data, isLoading}] = useLoginUserMutation();
const submitLogin = () => {
// pass in username password from the form
login({username, password});
}
Suppose if I console log out data and isLoading I assume that I will see data: {user: "abc", token: "xyz"}, because under network tab of my inspect window I can see the response of this network request, but instead I am seeing data: undefined
Does any have experience on solving this?
Oh I found the reason, it was a very careless mistake. I had to wrap the reducer to my store, which was what I was missing
In my case the issue was that I was trying to access the UseMutationResult object inside onClick callback. And the object was not updating inside the callback, even though in the component the values were accurate.
If I put the log outside it's working just fine.
here is an example for better understanding (inside handleAddPost the mutationResult is not updating)
Here is a code sample (in case link is not working):
const Component = () => {
const [addPost, mutationResult] = useAddPostMutation();
...
const handleAddPost = async () => {
...
console.log("INSIDE CALLBACK isLoading and other data is not updating:");
console.log(JSON.parse(JSON.stringify(mutationResult)))
...
};
// in the example this is wrapped in an useEffect to limit the number of logs
console.log(mutationResult.data,"OUTSIDE CALLBACK isLoading and other data is working:")
console.log(JSON.parse(JSON.stringify(mutationResult)))
return (
...
<Button
...
onClick={handleAddPost}
>
Add Post
</Button>
...

The data in Next.js shows as array, different from the JSON object returned by the API

I fetch data from Laravel API using getServerSideProps():
This is how I fetch the data:
function Product({ data }) {
console.log(data);
return (
<div>Hello</div>
)
}
export async function getServerSideProps() {
// Fetch data from external API
const res = await fetch(`http://localhost:8000/api/products/`, {
method: 'GET',
})
const data = await res.json()
// Pass data to the page via props
return { props: { data } }
}
export default Product
This is the output in the console:
So it means in order to get the actual value for a product I'll need to extract it from props like so: data.data[0].name - is there a better way to do it? It looks too complicated and prone to errors. Can I get a non-nested array in the first place?
*Also, the API returns a different object, and not an array like shown in the picture above
{"data":[{"id":1,"name":"some-product","price":"1250331.30","created_at":"2021-08-12T11:01:28.000000Z","updated_at":"2021-08-12T11:01:28.000000Z"},
{"id":2,"name":"some-other-product","price":"1141260.11","created_at":"2021-08-12T13:57:54.000000Z","updated_at":"2021-08-12T13:57:54.000000Z"}]}
You could use the destructuring notation ?
const { data } = await res.json()

getStaticProps with SWR "Error serializing `.initialData.config.transformRequest[0]` returned from `getStaticProps`"

I'm trying to use SWR in Next.js env.
const Best = (props: InferGetStaticPropsType<typeof getStaticProps>) => {
const { data } = useSWR('/best', apis.getBestProduct, {
initialData: props.initialData,
});
console.log(data);
return (
...SOME PRESENTER
);
};
export const getStaticProps: GetStaticProps = async () => {
const data = await apis.getBestProduct();
return { props: { initialData: data } };
};
export default Best;
I want to use useSWR with getStaticProps.
But this code makes error like this.
Server Error
Error: Error serializing `.initialData.config.transformRequest[0]` returned from `getStaticProps` in "/best".
Reason: `function` cannot be serialized as JSON. Please only return JSON serializable data types.
The data came well, I don't know why it doesn't work.
I'm using MacOS, custom Node.js server, and this is localhost.
getStaticProps sends your data to the front end by first serializing it with JSONā€”that is, it transforms data from a runtime JavaScript object into a string that can be parsed into a runtime JavaScript object by your front end.
However, JSON has certain limitations, one of which is that it cannot serialize functions. And somewhere in your data object you have a value that is a function. You need to clean up this data object before you return it from getStaticProps.
For example, suppose data.myFunction is a function, you could do something like:
export const getStaticProps: GetStaticProps = async () => {
const {myFunction, ...data} = await apis.getBestProduct();
return { props: { initialData: data } };
};
This will remove myFunction and leave all the other keys in data.

Resources