React-Admin 正在用相同的元素填充我的 <List>

React-Admin is populating my <List> with same element

codesandbox.io

我正在尝试使用 react-admin 创建一个漂亮的管理仪表板。
在我的后端使用 spring,这就是我将数据发送到 react-admin 的方式:

@GetMapping("admin/user")
ResponseEntity<List<User>> getAll()
{
   System.out.println(new Date());;

   HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.set("Content-Range", "posts 0-"+userRepository.findAll().size() + "/" + userRepository.findAll().size());
        responseHeaders.set("Origin", "http://localhost:3001");

    return ResponseEntity.ok()
             .headers(responseHeaders)
             .body(userRepository.findAll());
}

首先这行不通,其次,这离正确的解决方案还很远

不幸的是,我的客户一遍又一遍地渲染最后一个东西。
如您所见下方,带有id 129的元素被一遍又一遍地渲染!

在前端,react.js:

// Within main/parent component
class App extends Component {
  render() {
    return (
      <Admin dataProvider={restProvider('http://localhost:8080/admin')}>
         <Resource name="user" list={UserList}/>
      </Admin>
    );
  }
};

// child component
const UserList = (props) => (
   <List {...props}>
      <Datagrid>
         <TextField source="userID" />
         <TextField source="username" />
         <TextField source="firstName" />
         <TextField source="middleName" />
         <TextField source="lastName" />
         <TextField source="profileImageURL" />
         <DateField source="joiningTime" />
         <EditButton basePath="/posts" />
       </Datagrid>
    </List>
);

我想我需要一种方法来配置每个控制器响应 Content-Range header.

请注意,我返回的数据在 postman 中工作正常:

在这里试试:

https://codesandbox.io/s/react-admin-sample-l692r

每条记录必须有一个名为id的字段,在您的情况下代表您的userID字段。

使用 users 作为资源名称,而不是 user

如果您无法更改该服务器端,您可以在 javascript 中进行更改。

下面的示例代码应该可以工作。 将其添加到您的设置中的 AdminPanel.js 文件:

在您的后端中,取消注释以下行:

//data: json.map(record => ({"id": record.userID, ...record})),

//total: parseInt(headers.get('content-range').split('/').pop(), 10),

并更改以下行:

const apiUrl = "https://jsonplaceholder.typicode.com";

const apiUrl = "http://localhost:8080/admin";

import React from "react";
import { Admin, Resource, fetchUtils } from "react-admin";
import restProvider from "ra-data-simple-rest";
import { UserList, LoginCredentialList } from "./posts";
import { stringify } from "query-string";

const apiUrl = "https://jsonplaceholder.typicode.com";
const httpClient = fetchUtils.fetchJson;

const myDataProvider = {
    ...restProvider,
    getList: (resource, params) => {
        const { page, perPage } = params.pagination;
        const { field, order } = params.sort;
        const query = {
            sort: JSON.stringify([field, order]),
            range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]),
            filter: JSON.stringify(params.filter)
        };
        const url = `${apiUrl}/${resource}?${stringify(query)}`;

        return httpClient(url).then(({ headers, json }) => ({
            data: json,
            //data: json.map(record => ({"id": record.userID, ...record})),
            total: 10, //temporary hardcoded to avoid headers error.
            //total: parseInt(headers.get('content-range').split('/').pop(), 10),
        }));
    }
};

class AdminPanel extends React.Component {
    render() {
        return (
          <div>
              <Admin dataProvider={myDataProvider}>
                  <Resource name="users" list={UserList} />
                  <Resource name="loginCredential" list={LoginCredentialList} />
              </Admin>
          </div>
        );
    }
}

export default AdminPanel;

//                  <Resource name="posts" list={UserList} edit={PostEdit} create={PostCreate}/>

The never-ending challenge of consuming data from an API

上面的回答都是真的!
根据提出的问题,您如何为 <Datagrid> 提供一个 id 字段来迭代您的数据并唯一地呈现每个 row/element?

Note that the React-Admin dataProvider often returns a response with a json Object {count: <Number>, results: <Array>}. And the results array is often mapped onto the data key e.g. data: json.results

Here's what helped me while I used react-admin with a python/django backend.
我相信在大多数情况下,无论后端如何,了解 react-admin 如何使用数据(在本例中为 list)是至关重要的。有两种可能的解决方案:

  1. 如果您可以控制后端 (API),就像这里一样。
    那么请 update/refactor 您的唯一标识符(在这种情况下,userID) 成为 mapped/returned 作为一个普通的 id 字段。这将使任何使用 react-adminreact.js 的客户端更容易使用您的数据。

  2. 好的,所以您无法控制该后端 (API)!
    那么你将不得不使用这一行 //data: json.map(record => ({"id": record.userID, ...record})).

使用解决方案二不会太快!
使用 APIs 时存在最常见的陷阱。
当我们获取数据时,我们的客户端最初(array/list,在本例中json.results)是未定义的。
所以javascript将抱怨它 cannot read property 'map' of undefined.

如何解决undefined这样的挑战?

直接将您的数据作为 array 启动,或者指示 map() 仅在您的数据未定义时才 运行(通过包含此类检查,typeof json !== ‘undefined’ ).