列表视图抛出 TypeError

List view throwing TypeError

您的预期: 刚刚完成教程(成功)并尝试修改代码以使用我的 API。列表视图未显示数据且控制台有错误。

我能够添加 API 登录调用,在列表视图中我可以看到我的 API 已成功调用。

发生了什么: 页面显示标题和 "No results found"

控制台错误

index.js:2178 uncaught at handleFetch TypeError: newRecords.map is not a function
    at http://localhost:3001/static/js/bundle.js:69772:52
    at http://localhost:3001/static/js/bundle.js:69828:24
    at http://localhost:3001/static/js/bundle.js:69917:40
    at Array.reduce (<anonymous>)
    at ./node_modules/ra-core/lib/reducer/admin/resource/index.js.exports.default (http://localhost:3001/static/js/bundle.js:69914:30)
    at combination (http://localhost:3001/static/js/bundle.js:134671:29)
    at combination (http://localhost:3001/static/js/bundle.js:134671:29)
    at resettableAppReducer (http://localhost:3001/static/js/bundle.js:63329:16)
    at dispatch (http://localhost:3001/static/js/bundle.js:134907:22)
    at http://localhost:3001/static/js/bundle.js:119507:18
    at http://localhost:3001/static/js/bundle.js:132848:22
    at dispatch (http://localhost:3001/static/js/bundle.js:134462:18)
    at http://localhost:3001/static/js/bundle.js:134352:12
    at http://localhost:3001/static/js/bundle.js:133375:52
    at exec (http://localhost:3001/static/js/bundle.js:134015:5)
    at flush (http://localhost:3001/static/js/bundle.js:134056:5)
    at asap (http://localhost:3001/static/js/bundle.js:134029:5)
    at runPutEffect (http://localhost:3001/static/js/bundle.js:133372:69)
    at runEffect (http://localhost:3001/static/js/bundle.js:133321:307)
    at next (http://localhost:3001/static/js/bundle.js:133201:9)
    at currCb (http://localhost:3001/static/js/bundle.js:133274:7)

API 来自 DevTools 的响应数据(无法弄清楚如何格式化数据,所以它是一个屏幕截图。)

API 邮递员回复

{
"matches": [
    {
        "id": 1,
        "status": "DRAFT"
    },
    {
        "id": 2,
        "status": "DRAFT"
    },
    {
        "id": 3,
        "status": "DRAFT"
    },
    {
        "id": 4,
        "status": "READY"
    },
    {
        "id": 5,
        "status": "DRAFT"
    },
    {
        "id": 6,
        "status": "DRAFT"
    },
    {
        "id": 7,
        "status": "DRAFT"
    }
]

}

回应Headers

Access-Control-Allow-Origin: * 
Access-Control-Expose-Headers: Content-Range 
Connection: keep-alive 
content-range: matches 0-5/5 
Date: Fri, 20 Jul 2018 16:33:12 GMT 
ETag: W/"a5-KZYtsf9f1aSutDA6i7vGzddXNZk" 
X-Powered-By: Express 

Matches.js代码

import React from 'react';
import { List, Edit, Create, Datagrid, ReferenceField, TextField, EditButton, DisabledInput, LongTextInput, ReferenceInput, SelectInput, SimpleForm, TextInput } from 'react-admin';

export const MatchList = (props) => (
    <List {...props}>
        <Datagrid>
            <TextField source="id" />
            <TextField source="status" />
        </Datagrid>
    </List>
);

教程使用的是虚拟 api,我切换到 ra-data-simple-rest。我不得不对我的 API 输出进行一些更改以匹配预期的格式,所以我猜这可能是问题的根源,但错误没有帮助。

我本来有很多列,有些是空的,所以我只留下了ID和Status。我的结果中确实返回了 1 个附加字段 ("success": true)。我删除了它但得到了相同的结果。

其他信息:

环境

您的 API 的输出仍然不是立即数组。要么你改变你的 API 或者你改变你的 dataProvider.

选项 A:server-side 解决方案

改变你的API输出:

[
    {
        "id": 1,
        "status": "DRAFT"
    },
    {
        "id": 2,
        "status": "DRAFT"
    },
    ...
]

如果您利用可以告诉客户端服务器是否成功的 HTTP 状态(200、404、500),则不需要成功 属性* , ETC)。您也不需要总数 属性,因为您的 API 在 Content-range 响应 header.[=17= 中已经是 telling ]

Content-range: matches 0-5/5
                           ^ total

选项 B. client-side 解决方案

您可能正在使用某种形式的数据提供者,它是 ra-something-client。它可能有与此类似的部分。

const convertHTTPResponseToREST = (response, type, resource, params) => {
    const { headers, json } = response;

    switch (type) {
        case GET_LIST:
        case GET_MANY_REFERENCE: {
            if (!headers.has('content-range')) {
                throw new Error(
                    'The Content-Range header is missing in the HTTP Response. ' +
                        'The PostgREST client expects responses for lists of resources to contain ' +
                        'this header with the total number of results to build the pagination. ' +
                        'If you are using CORS, did you declare Content-Range in the ' +
                        'Access-Control-Expose-Headers header?'
                );
            }
            return {
                data: json.slice(),
                total: parseInt(
                    headers
                        .get('content-range')
                        .split('/')
                        .pop(),
                    10
                ),
            };
        }
        case CREATE:
            return { data: { ...params.data, id: json.id } };
        case DELETE:
            return { data: {} };
        default:
            return { data: json };
    }
};

您可以将其中的一部分改成:

return {
    data: json.data.slice(),
    total: json.total || parseInt(
        headers
            .get('content-range')
            .split('/')
            .pop(),
        10
    ),
};

或者只是:

return json;

* 由于某些Sencha/Ext JS 客户端,您可能习惯于发送成功属性。我知道我是。