React-Admin 正在用相同的元素填充我的 <List>
React-Admin is populating my <List> with same element
我正在尝试使用 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
)是至关重要的。有两种可能的解决方案:
如果您可以控制后端 (API),就像这里一样。
那么请 update/refactor 您的唯一标识符(在这种情况下,userID
) 成为 mapped/returned 作为一个普通的 id
字段。这将使任何使用 react-admin
或 react.js
的客户端更容易使用您的数据。
好的,所以您无法控制该后端 (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’
).
我正在尝试使用 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 jsonObject {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
)是至关重要的。有两种可能的解决方案:
如果您可以控制后端 (API),就像这里一样。
那么请 update/refactor 您的唯一标识符(在这种情况下,userID
) 成为 mapped/returned 作为一个普通的id
字段。这将使任何使用react-admin
或react.js
的客户端更容易使用您的数据。好的,所以您无法控制该后端 (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’
).