最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - react-admin: ERROR: The dataProvider threw an error. It should return a rejected Promise instead - easy fix? - Stac

programmeradmin4浏览0评论

In an react-admin 3.2.3 edit form I need to show related records (the list of job records) from a different resource. The relation is a bit weird and requires string parsing so I can't just use the built-in ReferenceField. That's why I am trying to call the dataProvider's getList function using the useGetList hook. Unfortunately I get an error on form rendering:

The dataProvider threw an error. It should return a rejected Promise instead

This is the getList function of my custom dataprovider:

 getList: (resource, params) => {
        console.log('DataProvider.GetList ');
        console.log(resource);
        console.log(params);
        const { page, perPage } = params.pagination;
        const { field, order } = params.sort;
        const query = {
            ...fetchUtils.flattenObject(params.filter),
            _sort: field,
            _order: order,
            _start: (page - 1) * perPage,
            _end: page * perPage,
        };
        const url = `${getUrl(resource)}?${stringify(query)}`;
        const paging = supportsPaging(resource);

        return httpClient(url).then(
            ({ headers, json }) => {
                var result = [];

                // Implementierung von clientseitigem Paging & Filtering
                var filtered = applyFilter(json, params.filter);
                if (!paging) {
                    filtered=applyPagination(filtered, page, perPage);
                }
                else {
                    result = filtered;
                }

                return {
                    data: result,
                    total: json.length 
                };
            }, ({ reason }) => {

                console.log(reason);
            }).catch((e)=>{
                console.log(e);
            });
    }

I use this custom ponent in the edit form.

export const CSEJobList = ({ ...props }) => {
    const form = useForm();
    var formdata = form.getState().values;
    console.log("CSEJobList");
    if (formdata && formdata.status && formdata.status.id >= 2) {
        var data = GetJobData({ 'filter': { type: 'abeitsschein_id_' + formdata.id } });
        return data;
    }
    else {
        return <div>Test</div>
    }
};
CSEJobList.defaultProps = { label: 'Arbeitsschein', addLabel: true };

  const GetJobData = (params) => {
        let parms = { "pagination": { "page": 0, "perPage": 25 }, "sort": { "field": "id", "order": "ASC" }, "filter": {} };
        const { data, loading, error } = useGetList('jobs', parms);
        if (loading) { return <LinearProgress />; }
        if (error) { return <p>ERROR</p>; }
        return <p>{data}</p>;
    };

This is just a basic test. Proper display of result data is not implemented yet since the call results in the mentioned error.

I read the documentation (.html#specialized-hooks) about querying the API, fiddled around a lot, but I fail because of my limited understanding of promises.

Is there an easy fix?

Update:

I changed the dataProvider getList function like so, return rejected promises as suggested:

getList: (resource, params) => {
    console.log('DataProvider.GetList ');
    console.log(resource);
    console.log(params);
    const { page, perPage } = params.pagination;
    const { field, order } = params.sort;
    const query = {
        ...fetchUtils.flattenObject(params.filter),
        _sort: field,
        _order: order,
        _start: (page - 1) * perPage,
        _end: page * perPage,
    };
    const url = `${getUrl(resource)}?${stringify(query)}`;
    const paging = supportsPaging(resource);

    return httpClient(url).then(
        ({ headers, json }) => {
            var result = [];

            // Implementierung von clientseitigem Paging & Filtering
            var filtered = applyFilter(json, params.filter);
            if (!paging) {
                filtered=applyPagination(filtered, page, perPage);
            }
            else {
                result = filtered;
            }

            return {
                data: result,
                total: json.length,  // Erfordert nun keinen speziellen Header mehr, CSE-Connect kompatibel
            };
        }, ({ reason }) => {
            return Promise.reject(reason);
        }).catch((e)=>{
            console.log(e);
            return Promise.reject(e);
        });
},

It had no effect. After some debugging I realized that in the GetJobData function the line

if (loading) { return <LinearProgress />; }

causes the error. Exactly the same works in other parts of the code, so the suspect is not LinearProgress. I actually have no Idea what causes the error. Debugging is hard to impossible because of timeouts.

This is the full stack trace:

useDataProvider.js:334 Uncaught Error: The dataProvider threw an error. It should return a rejected Promise instead.
    at performQuery (useDataProvider.js:334)
    at Proxy.<anonymous> (useDataProvider.js:163)
    at JSON.stringify.query (useQueryWithStore.js:116)
    at mitHookEffectList (react-dom.development.js:22030)
    at mitPassiveHookEffects (react-dom.development.js:22064)
    at HTMLUnknownElement.callCallback (react-dom.development.js:336)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:385)
    at invokeGuardedCallback (react-dom.development.js:440)
    at flushPassiveEffectsImpl (react-dom.development.js:25392)
    at unstable_runWithPriority (scheduler.development.js:697)
    at runWithPriority$2 (react-dom.development.js:12149)
    at flushPassiveEffects (react-dom.development.js:25361)
    at performSyncWorkOnRoot (react-dom.development.js:24251)
    at react-dom.development.js:12199
    at unstable_runWithPriority (scheduler.development.js:697)
    at runWithPriority$2 (react-dom.development.js:12149)
    at flushSyncCallbackQueueImpl (react-dom.development.js:12194)
    at flushSyncCallbackQueue (react-dom.development.js:12182)
    at batchedUpdates$1 (react-dom.development.js:24392)
    at Object.notify (Subscription.js:19)
    at Subscription.notifyNestedSubs (Subscription.js:92)
    at Subscription.handleChangeWrapper (Subscription.js:97)
    at dispatch (redux.js:222)
    at middleware.js:22
    at redux-saga-core.esm.js:1410
    at useDataProvider.js:300

In an react-admin 3.2.3 edit form I need to show related records (the list of job records) from a different resource. The relation is a bit weird and requires string parsing so I can't just use the built-in ReferenceField. That's why I am trying to call the dataProvider's getList function using the useGetList hook. Unfortunately I get an error on form rendering:

The dataProvider threw an error. It should return a rejected Promise instead

This is the getList function of my custom dataprovider:

 getList: (resource, params) => {
        console.log('DataProvider.GetList ');
        console.log(resource);
        console.log(params);
        const { page, perPage } = params.pagination;
        const { field, order } = params.sort;
        const query = {
            ...fetchUtils.flattenObject(params.filter),
            _sort: field,
            _order: order,
            _start: (page - 1) * perPage,
            _end: page * perPage,
        };
        const url = `${getUrl(resource)}?${stringify(query)}`;
        const paging = supportsPaging(resource);

        return httpClient(url).then(
            ({ headers, json }) => {
                var result = [];

                // Implementierung von clientseitigem Paging & Filtering
                var filtered = applyFilter(json, params.filter);
                if (!paging) {
                    filtered=applyPagination(filtered, page, perPage);
                }
                else {
                    result = filtered;
                }

                return {
                    data: result,
                    total: json.length 
                };
            }, ({ reason }) => {

                console.log(reason);
            }).catch((e)=>{
                console.log(e);
            });
    }

I use this custom ponent in the edit form.

export const CSEJobList = ({ ...props }) => {
    const form = useForm();
    var formdata = form.getState().values;
    console.log("CSEJobList");
    if (formdata && formdata.status && formdata.status.id >= 2) {
        var data = GetJobData({ 'filter': { type: 'abeitsschein_id_' + formdata.id } });
        return data;
    }
    else {
        return <div>Test</div>
    }
};
CSEJobList.defaultProps = { label: 'Arbeitsschein', addLabel: true };

  const GetJobData = (params) => {
        let parms = { "pagination": { "page": 0, "perPage": 25 }, "sort": { "field": "id", "order": "ASC" }, "filter": {} };
        const { data, loading, error } = useGetList('jobs', parms);
        if (loading) { return <LinearProgress />; }
        if (error) { return <p>ERROR</p>; }
        return <p>{data}</p>;
    };

This is just a basic test. Proper display of result data is not implemented yet since the call results in the mentioned error.

I read the documentation (https://marmelab./react-admin/Actions.html#specialized-hooks) about querying the API, fiddled around a lot, but I fail because of my limited understanding of promises.

Is there an easy fix?

Update:

I changed the dataProvider getList function like so, return rejected promises as suggested:

getList: (resource, params) => {
    console.log('DataProvider.GetList ');
    console.log(resource);
    console.log(params);
    const { page, perPage } = params.pagination;
    const { field, order } = params.sort;
    const query = {
        ...fetchUtils.flattenObject(params.filter),
        _sort: field,
        _order: order,
        _start: (page - 1) * perPage,
        _end: page * perPage,
    };
    const url = `${getUrl(resource)}?${stringify(query)}`;
    const paging = supportsPaging(resource);

    return httpClient(url).then(
        ({ headers, json }) => {
            var result = [];

            // Implementierung von clientseitigem Paging & Filtering
            var filtered = applyFilter(json, params.filter);
            if (!paging) {
                filtered=applyPagination(filtered, page, perPage);
            }
            else {
                result = filtered;
            }

            return {
                data: result,
                total: json.length,  // Erfordert nun keinen speziellen Header mehr, CSE-Connect kompatibel
            };
        }, ({ reason }) => {
            return Promise.reject(reason);
        }).catch((e)=>{
            console.log(e);
            return Promise.reject(e);
        });
},

It had no effect. After some debugging I realized that in the GetJobData function the line

if (loading) { return <LinearProgress />; }

causes the error. Exactly the same works in other parts of the code, so the suspect is not LinearProgress. I actually have no Idea what causes the error. Debugging is hard to impossible because of timeouts.

This is the full stack trace:

useDataProvider.js:334 Uncaught Error: The dataProvider threw an error. It should return a rejected Promise instead.
    at performQuery (useDataProvider.js:334)
    at Proxy.<anonymous> (useDataProvider.js:163)
    at JSON.stringify.query (useQueryWithStore.js:116)
    at mitHookEffectList (react-dom.development.js:22030)
    at mitPassiveHookEffects (react-dom.development.js:22064)
    at HTMLUnknownElement.callCallback (react-dom.development.js:336)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:385)
    at invokeGuardedCallback (react-dom.development.js:440)
    at flushPassiveEffectsImpl (react-dom.development.js:25392)
    at unstable_runWithPriority (scheduler.development.js:697)
    at runWithPriority$2 (react-dom.development.js:12149)
    at flushPassiveEffects (react-dom.development.js:25361)
    at performSyncWorkOnRoot (react-dom.development.js:24251)
    at react-dom.development.js:12199
    at unstable_runWithPriority (scheduler.development.js:697)
    at runWithPriority$2 (react-dom.development.js:12149)
    at flushSyncCallbackQueueImpl (react-dom.development.js:12194)
    at flushSyncCallbackQueue (react-dom.development.js:12182)
    at batchedUpdates$1 (react-dom.development.js:24392)
    at Object.notify (Subscription.js:19)
    at Subscription.notifyNestedSubs (Subscription.js:92)
    at Subscription.handleChangeWrapper (Subscription.js:97)
    at dispatch (redux.js:222)
    at middleware.js:22
    at redux-saga-core.esm.js:1410
    at useDataProvider.js:300
Share Improve this question edited Feb 27, 2020 at 8:49 elsni asked Feb 25, 2020 at 16:19 elsnielsni 2,0532 gold badges18 silver badges37 bronze badges 4
  • what import do you use for LinearProgress? – François Zaninotto Commented Mar 3, 2020 at 23:37
  • I use LinearProgress from react-admin – elsni Commented Mar 4, 2020 at 13:20
  • There is no reason this ponent can fail... So I have no idea why your code doesn't work. – François Zaninotto Commented Mar 6, 2020 at 16:31
  • LinearProgress works fine on other parts of the code, I have no Idea why this happens. – elsni Commented Mar 10, 2020 at 8:56
Add a ment  | 

3 Answers 3

Reset to default 3

Current implementation catchs the exception, if any, and say us that the exception should not be fired from the data provider, but the error should be returned as rejected promise:

Error: The dataProvider threw an error. It should return a rejected Promise instead.

Let's take a look to current code, it looks like this:

} catch (e) {
    if (process.env.NODE_ENV !== 'production') {
        console.error(e);
    }
    throw new Error(
        'The dataProvider threw an error. It should return a rejected Promise instead.'
    );
}

From this we can see that actual error is dumped to the console just before that as the mentioned error about rejected promise is fired.

Thus, to solve the problem, we need to scroll the console to the previously displayed error and fix it instead of the promise error, which is located below in the console and on the page itself. And if possible, also correct the provider to switch to the rejected promise. However, fixing the previous error will suffice.

if an error occurs, your dataProvider should return the following value:

import { HttpError } from 'react-admin'
...
return Promise.reject(new HttpError(message, status, body))

This is unrelated to OP's problem but I got this issue when I miss typed filters to filter:

<List filters={myPostFilters}>  // this should be plural "filters"
   // ...
</List>

If singular, somehow this will result in the same error as OP's.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论