How to mutate specific object in an array using SWR - reactjs

I have the following array
[
{
"idChatPublic": 17,
"idChatRoom": 2,
"idSender": "6c25110d-4256-42e1-8205-b75ece274487",
"username": "Hudson Thadeu Teixeira",
"message": "hello",
"avatar": null,
"createdAt": "12:43",
"chatLike": []
},
{
"idChatPublic": 33,
"idChatRoom": 2,
"idSender": "6c25110d-4256-42e1-8205-b75ece274487",
"username": "Hudson Thadeu Teixeira",
"message": "jam",
"avatar": null,
"createdAt": "13:07",
"chatLike": [
{
"idChatLike": 1,
"idChatPublic": 33,
"idUser": "",
"createdAt": "2022-02-14T08:59:34.000Z"
}
]
}
]
How can mutate an specific object of this array and add an object
to the "chatLike" array using SWR?
I have the following function:
async function sendLike() {
const newLike = {
idUser: myUser.userId,
}
mutate(
async (data) => {
console.log(data[messageIndex]) // This log returns specific object in the array
// Handle mutation
},
false
)
socket.emit('send_like', newLike)
}
Please guys I've been trying this for a while would be great If someone gives me a hand :D

You're using SWR with a websocket, which is an anti-pattern. SWR is meant for managing data that's fetched via REST or GraphQL requests, and it can be configured to refetch data on a regular interval. It's not a real time connection. Websocket on the other hand is real time. Consider if SWR is really best for your project - you probably don't need it.
Anyway, I also noticed some issues with how your mutate() is written so here's some feedback.
you must pass an ID into first argument
if you pass a function into mutate's second argument, it must return the new data
an easy way to update a specific item in an array is by using .map() and spread ... syntax
function sendLike() {
const newLike = {
idUser: myUser.userId,
}
// send request to update the source
// this is usually an REST request such as 'POST, UPDATE' etc
socket.emit('send_like', newLike)
// mutate local data
mutate(
'/api/chat', // ID must match ID used in the useSWR hook,
data => data.map(chat => chat.idChatPublic === idChat : {
...chat,
chatLike: [
...chat.chatLike
newLike
]
} : chat),
false
);
}

Related

Use data from graphql response in React

I guess this is a simple issue, but I am stuck here for a while, so any advice may be helpful!
I have a react app and I am calling a GraphQL api (with apollo). Inside an arrow function component I have:
const [executeQuery, { data }] = useLazyQuery(GET_ALL_TASKS);
const findId = (step) => {
executeQuery({
variables: {
"query": {
"state": "CREATED",
"taskDefinitionId": "something"
}
}
})
}
The query is successful and in the browser inspect panel I get this as the graphql response:
{
"data" : {
"tasks" : [ {
"id" : "2251",
"name" : "some_name",
"__typename" : "Task"
} ]
}
}
In my code I want to use the retrieved id. How can I isolate the id from the response? When I am trying to access the data I get an undefined error.
Thank you!
Not sure why you are wrapping your executeQuery in a function.
The data will be part of the response so you can get it like this:
const {data, loading} = executeQuery({
variables: {
"query": {
"state": "CREATED",
"taskDefinitionId": "something"
}
}
})
// may also need to check for the error state
if(loading){
console.log("Loading...")
}else{
/// the ids seem to be an array of objects
const ids = data.tasks.map((task)=> task.id)
console.log(ids)
}
For anyone who may have the same problem, I realized it is a caching error happening in apollo client. I couldn't figure out the solution. However, I temporarily solved it by downgrading the apollo client dependency to version 3.2.5

React API call, render data with QuickBase's new RESTful API

I'm trying to figure out what i'm doing wrong here... I've been out of coding for awhile and trying to jump back in for an external application utilizing QuickBase's RESTful API. I'm simply trying to get data from QuickBase to be used outside in an external app to create charts/graphs.
I'm not able to use GET as it gives me only the field names and no data, if I use POST, then I get the values of these fields as well. I'm able to get all the data rendered in the console, but am struggling to get each field rendered to be used in the app.
let headers = {
'QB-Realm-Hostname': 'XXXXXXXXXXXXX.quickbase.com',
'User-Agent': 'FileService_Integration_V2.1',
'Authorization': 'QB-USER-TOKEN XXXXXX_XXXXX_XXXXXXXXXXXXXXXX',
'Content-Type': 'application/json'
}
let body = {"from":"bpz99ram7","select":[3,6,80,81,82,83,86,84,88,89,90,91,92,93,94,95,96,97,98,99,101,103,104,105,106,107,109,111,113,115,120,123,224,225,226,227,228,229,230,231,477,479,480,481],"sortBy":[{"fieldId":6,"order":"ASC"}],"groupBy":[{"fieldId":40,"grouping":"equal-values"}],"options":{"skip":0,"top":0,"compareWithAppLocalTime":false}}
fetch('https://api.quickbase.com/v1/records/query',
{
method: 'POST',
headers: headers,
body: JSON.stringify(body)
})
.then(res => {
if (res.ok) {
return res.json().then(res => console.log(res));
}
return res.json().then(resBody => Promise.reject({status: res.status, ...resBody}));
})
.catch(err => console.log(err))
Hoping to get some help getting the data rendered to be used in React, as well as any tips from anyone who's used QuickBase's new API calls in their realm! And I apologize if it's an easy question/issue, haven't been in React for a couple years... and I'm feeling it!
Thanks!
A successful response from Quickbase for this call has a property data which is an array of the records returned. Each element of this array is an object where the FID for each field returned is a key for nested object - or objects for some field types - with the field's value. Here's a very contrived example:
{
"data": [
{
"1": {
"value": "2020-10-24T23:22:39Z"
},
"2": {
"value": "2020-10-24T23:22:39Z"
},
"3": {
"value": 2643415
}
}
],
"fields": [
{
"id": 1,
"label": "Date Created",
"type": "timestamp"
},
{
"id": 2,
"label": "Date Modified",
"type": "timestamp"
},
{
"id": 3,
"label": "Record ID#",
"type": "recordid"
}
]
}
If you put the data array of the response directly into state with const [quickbaseData, setQuickbaseData] = useState(res.data); for example, you need to keep the structure of the response in mind when accessing that data. If I want to get the value of FID 3 from the first record in the response I would need to use quickbaseData[0]["3"].value. For most field types value will be a string or integer but for some field types it will be an object. You can see the way values are returned for each field type in Field type details.
Depending on your needs you might consider processing the Quickbase response into a new, simpler array/object to use in your application. This is especially helpful if the value being returned needs additional processing such as converting into a Date() object. This would also allow you to make your application API agnostic since other than initially processing the response from Quickbase the rest of your application doesn't have to have any knowledge of how Quickbase returns queried data.
On the Quickbase side of things, there isn't the equivalent of 'SELECT *' so to get data for all fields of a table where you don't know the schema (or it changes frequently) you can run a GET on the Fields endpoint: https://developer.quickbase.com/operation/getFields an then use the field IDs in the response to make the POST call to /records/query

Make Axios Limit the Number of Responses

I am attempting to make an axios GET call to an API to retrieve some JSON data. The data is stored in an array with multiple objects each containing the same keys. There are hundreds of objects in this array but I only want to return the first ten. I am aware I can truncate the data set once it is returned but I am wondering if there is a way to limit the amount of responses to my API call.
Here is an example of the data set:
[
{
"userId": 1,
"id": 1,
"title": "The Great Gatsby",
"author": "F. Scott Fitzgerald"
},
{
"userId": 1,
"id": 2,
"title": "1984",
"author": "George Orwell"
},
{
"userId": 1,
"id": 3,
"title": "The Count of Monte Cristo",
"author": "Alexandre Dumas"
},
]
and my axios request is simple as well:
router.get('/', (req, res) => {
axios.get(`https://jsonwebsit.info.com/posts`)
.then( response => {
res.send(response.data)
})
.catch(err => {
console.log('Error getting all data from API', err)
})
});
Actually, you can limit the number of responses from a certain API endpoint.
Just add params as an object as a second parameter while making the request.
For example:
componentDidMount() {
axios.get('https://jsonplaceholder.typicode.com/todos',{
params: {
_limit: 10
}
})
.then((res) => {
this.setState({
todos: res.data
});
})
}
Here you are limiting the response to 10 from jsonplaceholder API.
You could also call https://jsonplaceholder.typicode.com/todos/?_limit=10 and would get the same result.
Hope it helps.
On your side there's nothing you can do until pagination is implemented on API side. Depending on the way it's implemented, you will probably make requests to API sending params like offset, page, limit- these are the most common params' names saying how many elements should API return. But if that's 3rd party provider and their docs are not saying anything about such possibility, you're most likely won't be able to do what you want

How I can read and storage a JSON object from Dynamodb into React?

I am getting a JSON object from a Lambda function. When I get a specific value from the JSON object and storage it into an array it works fine. I don't know how to storage the whole JSON object on any structure in React. The idea is to storage the JSON object to make some calculations later with the values.
I am using "json.map" get the values
Here is where I call the API gateway and fecth the json object:
componentDidMount() {
fetch('https://llzgbat7hi.execute-api.us-east-2.amazonaws.com/api/getrange?domain=demo.com&cont=5')
.then(res => res.json())
.then(json => {
const RecordRowCount = json.map(item => item.RecordRowCount)
this.setState({ tasks: RecordRowCount })
});
}
The code above show how I get the value RecordRowCount and storage it into an array but I need to fecth the whole JSON object
This is the actual JSON structure returned from DB:
[
{
"Id": "123455",
"Customer": 100,
"Domain": "demo.com",
"OrgName": "demo.com",
"ReportMetadataEmail": "demo#me.com",
"ReportMetadataExtraContactInfo": "postmaster#demo.com"
},
{
"Id": "123456",
"Customer": 101,
"Domain": "demo1.com",
"OrgName": "demo1.com",
"ReportMetadataEmail": "demo1#me.com",
"ReportMetadataExtraContactInfo": "postmaster#demo1.com"
}
]
I want to map that JSON object into any React structure (Ex Array)
Thanks a lot #AppleJam, #Taki and #tcoulson
You were right. I just assigned json to tasks and it worked, now my tasks array hold all the json object.
Thanks

Combining data from two different API and parsing the response (nodes typescript)

I'm currently working on a RESTful API backend using nodejs with typescript where I need to gather information from multiple different APIs and parse the result and pass on the parsed information to the frontend.
Right now I'm working on a API route where I gather information from two different external API routes, I gather the data from there with https. I send the data onward to my Objecthandler in the form [object Object],[object Object] because I push the response from my first http call into an array and my second http response into another array which I then push onto a third array that is the combined data from both responses.
const first: object [] = [
];
const second: object [] = [
];
const combined: object [] = [
];
My object handler code looks like this:
function ObjectHandlerAvainsanat(obj: any): object[] {
const keywords: object [] = [
];
if (obj instanceof Array) {
obj.forEach((e: any) => {
const results = e.results.map((x: any) => x);
const vals = {
localname: results.localname,
prefLabel: results.prefLabel,
altLabel: results.altLabel,
};
keywords.push(vals);
});
return keywords;
}
}
However, I get the error that
const results = e.results.map((x) => x);
^
TypeError: Cannot read property 'map' of undefined
The actual data inside the http response looks like this, where I want the values from inside the results object array:
{
"#context": {
"skos": "http://www.w3.org/2004/02/skos/core#",
"isothes": "http://purl.org/iso25964/skos-thes#",
"onki": "http://schema.onki.fi/onki#",
"uri": "#id",
"type": "#type",
"results": {
"#id": "onki:results",
"#container": "#list"
},
"prefLabel": "skos:prefLabel",
"altLabel": "skos:altLabel",
"hiddenLabel": "skos:hiddenLabel",
"#language": "FI"
},
"uri": "",
"results": [
{
"uri": "http://www.yso.fi/onto/yso/p22020",
"type": [
"skos:Concept",
"http://www.yso.fi/onto/yso-meta/Concept"
],
"localname": "p22020",
"prefLabel": "pyydystä ja päästä -kalastus",
"lang": "fi",
"altLabel": "catch and release -kalastus",
"vocab": "yso"
},
{
"uri": "http://www.yso.fi/onto/yso/p22337",
"type": [
"skos:Concept",
"http://www.yso.fi/onto/yso-meta/Concept"
],
"localname": "p22337",
"prefLabel": "CATCH-22",
"lang": "fi",
"vocab": "yso"
}
Does anyone here know what I'm doing wrong? Thanks in advance for all the help,
Br,
Victor
TypeError: Cannot read property 'map' of undefined
e.results is undefined. This is a fact irrespective of your result object you are showing.
Fix
console.log(e) and go from there.
(assuming e is your http response)
Based on the HTTP response you provided, e is a JSON object, so you can call:
let newVar = JSON.parse(e);
and then try to pull results using:
newVar.results.map((x: any) => x);
Hope this helps...

Resources