Parsing the results of a 'useQuery'

I am experimenting with parsing the results from a ‘useQuery’

Here is my code

const assets = useQuery(Main.CitizenInvitation);
const obj = JSON.stringify(assets);
con> sole.log ("asset : " + obj);
const obj2 = JSON.parse(obj);
console.log ("obj contracts : " + JSON.stringify(obj2.contracts[0]));
console.log ("templateId : " + JSON.stringify(obj2.contracts.templateId));

Here is the console.log output:

asset : {“contracts”:[{“templateId”:“5930f9c206352112718aaa4bf0104f368d4b4763cf201e055073cdea03bc3301:Main:CitizenInvitation”,“contractId”:“00bbb0f3c6bd9a27d8ffe304bc6aca8b0cc058eea3e483704df0469be9776fa9c5”,“signatories”:[“Operator”],“observers”:[“Alice”],“agreementText”:“”,“payload”:{“operator”:“Operator”,“citizen”:“Alice”,“roletype”:“Citizen”}}],“loading”:false}

obj contracts : {“templateId”:“5930f9c206352112718aaa4bf0104f368d4b4763cf201e055073cdea03bc3301:Main:CitizenInvitation”,“contractId”:“00bbb0f3c6bd9a27d8ffe304bc6aca8b0cc058eea3e483704df0469be9776fa9c5”,“signatories”:[“Operator”],“observers”:[“Alice”],“agreementText”:“”,“payload”:{“operator”:“Operator”,“citizen”:“Alice”,“roletype”:“Citizen”}}

templateId : undefined

The results are that I can parse and console.log the ‘assets’ and the ‘contract’, but I cannot arrive at displaying the ‘templateId’ as it is ‘undefined’

Any suggestions ?

1 Like

It looks like you are printing obj2.contracts.templateId instead of obj2.contracts[0].templateId. templateId is a property on each contract not on the array of contracts.

1 Like

Tried that as well but received Type Error

1 Like

That looks like contracts is empty and therefore contracts[0] is undefined. Do you see any output from the second console.log statement?

1 Like

See my above message for all the console logs. The contract is not empty.
If I apply the same statement from a static Const with exactly the same JSON it works, but for some reason for a object that comes from the stream it doesn’t

Are you sure you get the same log after making the changes? Looking at your code I’m also a bit confused as to why you first call JSON.stringify only to then call JSON.parse again.

I agree that it would be much simpler to do just a JSON.parse but it creates errors

const assets = useQuery(Main.CitizenInvitation);
//const obj = JSON.stringify(assets);
//console.log ("asset : " + obj);
const obj2 = JSON.parse(assets);
console.log ("obj contracts : " + JSON.stringify(obj2.contracts[0]));

Creates the following error :

Uncaught SyntaxError: Unexpected token o in JSON at position 1
at JSON.parse ()
at Default (Default.js:32)
at renderWithHooks (react-dom.development.js:14803)
at mountIndeterminateComponent (react-dom.development.js:17482)
at beginWork (react-dom.development.js:18596)
at HTMLUnknownElement.callCallback (react-dom.development.js:188)
at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
at invokeGuardedCallback (react-dom.development.js:292)
at beginWork$1 (react-dom.development.js:23203)
at performUnitOfWork (react-dom.development.js:22154)
at workLoopSync (react-dom.development.js:22130)
at performSyncWorkOnRoot (react-dom.development.js:21756)
at scheduleUpdateOnFiber (react-dom.development.js:21188)
at updateContainer (react-dom.development.js:24373)
at react-dom.development.js:24758
at unbatchedUpdates (react-dom.development.js:21903)
at legacyRenderSubtreeIntoContainer (react-dom.development.js:24757)
at Object.render (react-dom.development.js:24840)
at Module…/src/index.js (index.js:16)
at webpack_require (bootstrap:785)
at fn (bootstrap:150)
at Object.1 (index.js:28)
at webpack_require (bootstrap:785)
at checkDeferredModules (bootstrap:45)
at Array.webpackJsonpCallback [as push] (bootstrap:32)
at main.chunk.js:1

If you are available… I can do a screenshare.

You shouldn’t need either JSON.parse or JSON.stringify. Use the result directly:

const assets = useQuery(…);
console.log(assets.contracts);

How can I get to the details in the contracts ? I need to retrieve a specific value ? How do I get to that value ?

In the example above , I need to retrieve the “roletype” value

It’s a JSON object, you can just use .field to drill down so assets.contracts[0].payload.roletype.

console.log ("roletype : " + JSON.stringify(assets.contracts[0]));

displays

roletype : {“templateId”:“5930f9c206352112718aaa4bf0104f368d4b4763cf201e055073cdea03bc3301:Main:CitizenInvitation”,“contractId”:“00bbb0f3c6bd9a27d8ffe304bc6aca8b0cc058eea3e483704df0469be9776fa9c5”,“signatories”:[“Operator”],“observers”:[“Alice”],“agreementText”:“”,“payload”:{“operator”:“Operator”,“citizen”:“Alice”,“roletype”:“Citizen”}}

console.log ("roletype : " + JSON.stringify(assets.contracts[0].payload));

displays

`console.log ("roletype : " + JSON.stringify(assets.contracts.payload));

displays

roletype : undefined

console.log ("roletype : " + assets.contracts[0].payload);

displays

@bartcant Don’t forget that the result of a useQuery is a QueryResult. One needs to make sure that it is not loading and that the number of obj.contracts.length > 0 before you access a contract payload. Those things will change once the effect gets executed by React and the underlying fetch is resolved.

I have a sneaky suspicion that the errors you are seeing are due to the timing of when you see the results from the useQuery hook. Remember in that in Javascript

>> var x = []
Array []
>> x[0]
undefined
>> x[0].foo
TypeError: x[0] is undefined

Dealing with these confusing states makes me long for the safety of effect tracking monads.

To be safe, try assets.contracts.map(c => c.payload). As @Leonid_Rozenberg said I suspect it’s called twice once while the list is still loading and it’s empty and then once the entry is there.

Issue Solved :grinning:

const QueryResult = useQuery(Main.CitizenInvitation);
const assets = QueryResult.contracts.map(c => c.payload.roletype);
const roletype = JSON.stringify (assets);
console.log ("Roletype : " + roletype)

Thanks @cocreature @Leonid_Rozenberg !!!