Is there a way to get rid of the Runaway Promise warning when using react-query - react-query

I am using react-query useQuery as follows:
const { isLoading, error, data } = useQuery('repoData', () => {
return fetch('https://api.github.com/repos/tannerlinsley/react-query').then(res =>
res.json()
)
}
)
It generates the following warning:
Warning: a promise was created in a handler at webpack-internal:///./node_modules/react-query/es/core/retryer.js:68:50 but was not returned from it.
Is there anyway to remove it.
I am using Typescript

Related

Suspense returns data too fast in #tanstack/react-query v4

I am upgrading a React app from react-query v3 to #tanstack/react-query v4.
Almost everything works, but I'm having a problem with Suspense.
I have a react component:
const WrapperPageEdit: React.FC<MyProps> = ({
pageUuid,
redirect,
}: MyProps) => {
const FormPage = React.lazy(() => import('./FormPage'));
const { data } = usePageView(pageUuid);
if (data?.[0]) {
const pageObjectToEdit= data[0];
const content = pageObjectToEdit.myStuff.content;
return (
<Suspense
fallback={<Trans id="loading.editor">Loading the editor...</Trans>}
>
<FormPage
id={uuid}
content={content}
redirect={redirect}
/>
</Suspense>
);
}
return <p>No data.</p>;
};
And here's my query:
export function usePageView(
uuid: string,
): UseQueryResult<DrupalPage[], Error> {
return useQuery<DrupalPage[], Error>(
queryKeyUsePageView(uuid),
async () => {
return fetchAnon(getPageByPageUuid(uuid));
},
{
cacheTime: YEAR_MILLISECONDS,
staleTime: YEAR_MILLISECONDS,
onSuccess: (data) => {
if (data?.[0]) {
data.map((element) => processResult(element));
}
},
},
);
}
This works in v3 but fails in v4 with the following error:
TypeError: Cannot read properties of undefined (reading 'content')
The reason the property is undefined is because that property is set by the processing in onSuccess (data.map).
The issue appears to be that in v4, the component WrapperPageEdit is refreshed before onSuccess in the usePageView query has finished processing, whereas in v3, the component WrapperPageEdit is not refreshed until the onSuccess data.map is complete.
How can I correctly fix this? I can write some additional code to try to check whether the onSuccess data.map is complete, but since react-query handled this automatically in v3, I'd like to rewrite my code in v4 so that it is the same.
The problem is likely that you are mutating the data in onSuccess. Directly modifying data in callbacks is not a good idea. Instead, do your transformation for example directly in the queryFn:
async () => {
const data = fetchAnon(getPageByPageUuid(uuid));
if (data?.[0]) {
data.map((element) => processResult(element));
}
return data
},
other good places to do data transformation is e.g. the select option, but it should always happen in an immutable way, because otherwise, you are overwriting the cached data inadvertently. React prefers updates to be immutable.

How to handle non explicit errors inside sails.js helpers?

I am trying to figure out how the Error handling in Sails.js works. Unfortunatley the code examples in the docs do not cover this use case.
The problem is I keep getting this error:
UsageError: `.intercept()` handler returned `undefined`, but this should never happen.
Regardless, here is a summary of the original underlying error:
Now all I am trying to do is call a helper and if it fails, then I want to catch the error (any), log it and run some code. If I wouldn't be using Sails but normal promises I would have handled it like this:
await helper().catch((err) => { // run some code }
In Sails I should be able to use .intercept() instead of .catch()
My code looks like this:
// ExportController.js
const csv = await sails.helpers.files.convertToCsv(data)
.intercept((err) => {
sails.log.error(err)
req.addFlash('error_messages', 'Error parsing data to csv!')
return res.redirect(`/`);
})
// convert-to-csv.js
if (!Array.isArray(inputs.data)) {
throw new Error('invalid inputs.data type: ' + typeof inputs.data)
};
Now how can I avoid getting this error?
The code examples show only cases where errors that are explicitly added to the exits object are handled, but not for general error handling.
In the docs it says that if the filter argument is
not provided, ALL errors will be intercepted.
Or is that only true for db queries? Because the .intercept() doc section is in that subcategory.
You could use “throw ‘errorCode’;” for example:
Set the exits:
exits {
errorWithCsvFile: {
responseType: 'badRequest'
}
}
const csv = await sails.helpers.files.convertToCsv(data)
.intercept(‘somethingWrongCode’, ‘errorWithCsvFile’)
... // Other handles
.intercept(err => new Error(err))
Alternative:
try {
...
const csv = await sails.helpers.files.convertToCsv(data)
.intercept((err) => {
sails.log.error(err)
req.addFlash('error_messages', 'Error parsing data to csv!')
throw 'badRequest';
})
...
} catch (err) {
sails.log.err(err);
return res.redirect(`/`);
}

redux-saga: why does `yield call (func, params)` fail but `yield call (()=>func(params))` succeed?

Here is my code that fails at the line with the comment //fails:
import {API} from "aws-amplify";
function* watchSitesRequested(dispatch) {
const watchAction = ('SITES_FETCH_REQUESTED');
const APIname="MyAPIGatewayAPI";
const APIpath="/configmagic/sites";
const APIinit={
headers: {
'Accept': 'application/json'
},
response: true,
};
while (true) {
yield take(watchAction);
try {
const request = yield call(API.get, APIname, APIpath, APIinit); //fails
yield put({type: "SITES_FETCH_SUCCEEDED", payload: {sites: request.data}});
} catch (e) {
yield put({type: "SITES_FETCH_FAILED", message: e.message})
}
}
}
Console error is:
TypeError: Cannot read property '_api' of null
at API.js:298
at step (API.js:137)
at Object.next (API.js:67)
at API.js:39
at new Promise (<anonymous>)
[snip]
But if I change the call to API.get as follows, it behaves as desired:
const request = yield call(() => API.get(APIname, APIpath, APIinit))
Why?
yield call() I think is supposed to accept multiple parameters after the function, and it should behave fine with the Promise that API.get() returns, shouldn't it?
You should call it like this:
const request = yield call([API, API.get], APIname, APIpath, APIinit)
or
const request = yield call([API, 'get'], APIname, APIpath, APIinit)
This is because API is an instance of the class APIClass.
Javascript has crazy rules of passing this when calling an instance method. Basically, it only works as intended when you directly write API.get() in code. But when you shedule a call via a call effect, the effect object only stores API.get function reference, losing this reference.
For this to be passed correctly, you should use call([context, fn], ...args).

TypeError seneca indexof if not a function during respond

I have written a simple action which connects to mongo db using seneca-mongo store module, execute a list query and get the results. I can see that the query was successful and the correct results were fetched. When I try to send these results back to the client, the respond call errors out with following message and stack trace.
ERROR act root$ OUT cmd:getparams,role:diff 11 {cmd:getparams,role:diff,payload:{id:scalaScan}} ENTRY (dqk22) - seneca: Action cmd:getparams,role:diff callback threw: k.indexOf is not a function. act_callback {message:k.indexOf is not a function,pattern:cmd:getparams,role:diff,instance:Seneca/0.7.2/d0twcki9cmxg/1485517 TypeError: k.indexOf is not a function
at /scratch/DiffAnalyzer/node_modules/seneca/node_modules/seneca-web/web.js:851:13
at Function.forEach (/scratch/DiffAnalyzer/node_modules/lodash/dist/lodash.js:3298:15)
at Object.defaultmodify [as modify] (/scratch/DiffAnalyzer/node_modules/seneca/node_modules/seneca-web/web.js:850:7)
at respond (/scratch/DiffAnalyzer/node_modules/seneca/node_modules/seneca-web/web.js:654:22)
at Seneca.<anonymous> (/scratch/DiffAnalyzer/node_modules/seneca/node_modules/seneca-web/web.js:401:7)
at act_done (/scratch/DiffAnalyzer/node_modules/seneca/seneca.js:1554:16)
at /scratch/DiffAnalyzer/node_modules/gate-executor/gate-executor.js:127:20
at Seneca.<anonymous> (/scratch/DiffAnalyzer/analyze.js:613:5)
at act_done (/scratch/DiffAnalyzer/node_modules/seneca/seneca.js:1554:16)
at /scratch/DiffAnalyzer/node_modules/gate-executor/gate-executor.js:127:20
at /scratch/DiffAnalyzer/node_modules/seneca-mongo-store/mongo-store.js:329:21
at /scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:271:33
at /scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:778:35
at Cursor.close (/scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:1009:5)
at Cursor.nextObject (/scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:778:17)
at Cursor.each (/scratch/DiffAnalyzer/node_modules/mongodb/lib/mongodb/cursor.js:264:12)
The action that I have written is
seneca.add("role:diff,cmd:getparams", function(msg, respond) {
seneca.ready(function() {
var collection = seneca.make$("paramStore");
var f = msg.payload;
seneca.log.info("Filter", f);
collection.list$(f, function(err, ob) {
if (err) {
seneca.log.error(err);
respond(err);
} else {
seneca.log.info("Result", ob);
respond(null, ob);
}
});
});
});
The same piece of code was working and now I am getting this error. Not sure what changed. Any help/suggestions are greatly appreciated.
The issue I was facing was because of this bit of code in the module's js file
if( _.isObject( result.out ) ) {
_.each(result.out,function(v,k){
if(~k.indexOf('$') && 'http$' !== k) {
delete result.out[k]
}
})
The _.each function is meant to parse a JSON object, where in my case the out was actually a JSON array. Wrapping the array into an object resolved it.

Suppressing/Catching the ValidationError error from Mongoose

I have a static method setup that will verify if an object follows the schema of the model properly, and I've got the validation itself working just fine, but I can't get Mongoose to hide the ValidationError error that displays in the console.
The static method for the validation is:
fieldSchema.statics.testValidate = function( field ) {
return new Promise( ( res, rej ) => {
new this( field ).validate( err => {
if ( err ) return rej( err )
res( true )
} )
})
}
Then when I execute it:
Field.testValidate( fieldData )
.then(data => {
console.log('OK!', data)
})
.catch( err => {
console.error('FAILED:',err)
})
.finally(() => Mongoose.connection.close())
And like I said, I can get it to validate the data, but it will always show this error:
Unhandled rejection ValidationError: Field validation failed
at MongooseError.ValidationError ....
(Note: Im using Bluebird for my JS promises, incase it has anything to do with the then/catch somehow)
The script execution keeps going on with the code, so that means that it doesnt actually kill the script or anything, it just logs the error to the console. But since this function is meant to validate, its not really an "error", so is there a way to hide this from the console? (Just for this function, not for ALL Mongoose errors)
Thanks
validate already returns a promise so you don't need to wrap it in a new promise. The reason you see the error logged to the console is because of the fact that you're wrapping it in a new promise thus preventing the original promise from ever being caught i.e. Unhandled rejection.
fieldSchema.statics.testValidate = function(fieldData) {
return new this(fieldData).validate()
}