Javascript fetch API in react-flux - javascript

I am studying the flux-react-router-example by #Dan Abramov, I notice in the Fetch API code here: The fetch API has a return promise that has a nested return inside:
return fetch(url).then(response =>
response.json().then(json => {
const camelizedJson = camelizeKeys(json);
const nextPageUrl = getNextPageUrl(response) || undefined;
return {
...normalize(camelizedJson, schema),
nextPageUrl
};
})
);
I am confused with this nested returns, why is this used here? Why not just return response.json()?
Seems like if I do the same thing, I will get a undefined value

The json retrieved from the response is
converted to camelCase using humps
un-nested using normalizr for easier handling in combination with the redux store
enriched with the next page url, parsed from the link header
More discussion and reasoning about why storing nested response objects in the store is usually a bad idea can be found at the React JS Google Group.

Related

RTKQ - Select data without hooks

I'm trying to select cached data from RTKQ without using the auto-generated query hook, but I'm having trouble understanding the docs
const result = api.endpoints.getPosts.select()(state)
const { data, status, error } = result
This is how the docs describe how to access the data, but I can't find any references on how to inject the state object "select()(state)".
I can't figure out how to access the data if I only call the select?
api.endpoints.getPosts.select()
Can someone explain me the difference between "select()" and "select()(state)"
Or what is the optimal solution to access the cached data from RTKQ?
The result of api.endpoints.getPosts.select() is a selector function for the result of using the "getPosts" endpoint without arguments.
Similarly, result of api.endpoints.getPosts.select({ page: 5 }) is a selector function for the result of using the "getPosts" endpoint the argument { page: 5 }.
A selector function is then called as selector(state) or passed into useSelector(selector).
If you write that altogether, you end up with api.endpoints.getPosts.select()(state).
#phry
Thank you for your answer! I'm not 100% sure I understood your answer. But it pointed me in a direction that enabled me to get the data.
I ended up creating a selector like the docs.
export const selectUser = (state) => userApi.endpoints.getUser.select()(state);
and in my function, I referenced it with getting the exported store from configureStore() method
const { data } = selectUser(store.getState());
But I'm not sure if this is the intended way to do it.

("[object Promise]") cannot be serialized as JSON

Full error:
Error: Error serializing .b returned from getStaticProps in "/".
Reason: object ("[object Promise]") cannot be serialized as JSON.
Please only return JSON serializable data types.
I am trying to call one of my functions that retrieves some data from an API endpoint however when trying to pass this data to props I get an error. I am not exactly sure what I am doing wrong as the fetch call works if its within GetStaticProps but I want all my logic for fetch calls to exist within a separate js page to reduce redundancies, however when doing so this error is created.
export async function getStaticProps() {
let b = WordpressService.getPageByIdTest(50);
return {
props: {
b: b,
},
revalidate: 30
}
}
const WordpressService = {
async getPageByIdTest(id) {
const resIndexPage = await fetch(`${url}pages/${id}`);
const indexPageData = await resIndexPage.json();
return indexPageData;
}
}
I was going over the latest version of nextjs and I did notice that the demo was odd when I ran it. Specifically, I got this error when running their example:
Error: Additional keys were returned from getStaticProps. Properties
intended for your component must be nested under the props key, e.g.
export async function getSortedPostsData() {
// Instead of the file system,
// fetch post data from an external API endpoint
const res = await fetch('..')
return res.json()
}
This is not exactly your issue but assigning the props object via res.json() also caused the same error you are experiencing.
So, for me, using node 15 I changed my api call to:
export async function getStaticProps() {
const url = `https://my-url`
const result = await fetch(url)
return { props: {
result: await result.json()
}}
}
And this solved my problem. So Ivar's comment looks correct - await the result and then in my case I had to also await the json result from node-fetch so that the promises completed properly.
It can be easily solved with the package "superjson".
Effective and easy to use.
https://www.npmjs.com/package/superjson
for me, I wanted to convert "QuerySnapshot" from firestore which has timestamps in it.
posts = (await getDocs(postQuery)).docs.map((postDoc) => {
return superjson.stringify(postDoc);
});
picture from: https://www.npmjs.com/package/superjson

Unpack nested JSON in Next.js

I am attempting to unpack nested JSON via a fetch function I created. But, I am unsure how to get a specific array, for example pull the 'date' from index of 1. Currently, this is what I have:
Home.getInitialProps = async function() {
const res = await fetch('https://api.covidtracking.com/v1/us/daily.json')
const data = await res.json()
return {
//Obviously this is providing me with an error
data[1].date
}
}
My JSON:
[{"date":20210112}, {"date":20210111}, {"date":202101131}]
What is the correct way to do this, and subsequently get the values inside of the array?
try this
return {
date: data[0]['date']
}
If you're using Next.js 9.3 or newer, we recommend that you use
getStaticProps or getServerSideProps instead of getInitialProps.
https://nextjs.org/docs/api-reference/data-fetching/getInitialProps

Vue Array converted to Proxy object

I'm new to Vue. While making this component I got stuck here.
I'm making an AJAX request to an API that returns an array using this code:
<script>
import axios from 'axios';
export default {
data() {
return {
tickets: [],
};
},
methods: {
getTickets() {
axios.get(url)
.then((response) => {
console.log(response.data) //[{}, {}, {}]
this.tickets = [...response.data]
console.log(this.tickets) //proxy object
})
},
},
created() {
this.getTickets();
}
};
</script>
The problem is, this.tickets gets set to a Proxy object instead of the Array I'm getting from the API.
What am I doing wrong here?
Items in data like your tickets are made into observable objects. This is to allow reactivity (automatically re-rendering the UI and other features). This is expected and the returned object should behave just like the array.
Check out the reactivity docs because you need to interact with arrays in a specific pattern or it will not update on the ui: https://v3.vuejs.org/guide/reactivity-fundamentals.html
If you do not want to have reactivity - maybe you never update tickets on the client and just want to display them - you can use Object.freeze() on response.data;
if you want reactive information use toRaw
https://vuejs.org/api/reactivity-advanced.html#toraw
const foo = {}
const reactiveFoo = reactive(foo)
console.log(toRaw(reactiveFoo) === foo) // true
or use unref if you donot want ref wrapper around your info
https://vuejs.org/api/reactivity-utilities.html#unref
You can retrieve the Array response object from the returned Proxy by converting it to a JSON string and back into an Array like so:
console.log(JSON.parse(JSON.stringify(this.tickets)));
You're not doing anything wrong. You're just finding out some of the intricacies of using vue 3.
Mostly you can work with the proxied array-object just like you would with the original. However the docs do state:
The use of Proxy does introduce a new caveat to be aware of: the proxied object is not equal to the original object in terms of identity comparison (===).
Other operations that rely on strict equality comparisons can also be impacted, such as .includes() or .indexOf().
The advice in docs doesn't quite cover these cases yet. I found I could get .includes() to work when checking against Object.values(array). (thanks to #adamStarrh in the comments).
import { isProxy, toRaw } from 'vue';
let rawData = someData;
if (isProxy(someData)){
rawData = toRaw(someData)
}

Firebase firestore - Data must be an object, but it was: a custom Object object

I'm using Firestore in conjunction with realtime database in order to provide a user presence system for my application.
Update: article I followed
https://blog.campvanilla.com/firebase-firestore-guide-how-to-user-presence-online-offline-basics-66dc27f67802
In one of the methods I use this code here:
const usersRef = this.$fireStore.collection('users').doc(uid)
const whoIsOnlineRef = this.$fireDb.ref('.info/connected')
whoIsOnlineRef.on('value', (snapshot) => {
this.$fireDb.ref(`/status/${uid}`)
.onDisconnect()
.set('offline')
.then(() => {
usersRef.set({ online: true }, { merge: true })
this.$fireDb.ref(`/status/${uid}`).set('online')
})
})
The .set method, however, is giving me the error mentioned in the title and I can't quite understand why. I'm simply passing a javascript object to .set method and this should technically work.
Can you spot what is wrong with the code?
Looks like the reason why this wasn't working is that the code was running on the server in an SSR application.
I moved that very same logic to the browser and it started working nicely. I still don't see why this wouldn't work in the server as, at the end of the day I was still passing a simple js object to the .set() method.
Either way, there you have it

Categories

Resources