I have problem with <ReferenceField>
.
On my <List>
page, I have rows with UserId
and ToolId
that I need reference.
I want to show user name
and tool code
.
But these two columns get stuck in loading state, even though the dataProvider
, GET_MANY
request succeeded for users
and tools
.
When I console.log(data)
, it the data is all there but somehow it's not rendered into <ReferenceField>
. And It no error is logged at all.
Any idea what am I doing wrong? Or what's happening?
EDIT: I have updated react-admin and now its not displaying loading bar, but just display nothing.
Here is code of List:
export const B_toolList = props => (
<List {...props}>
<Datagrid rowClick="edit">
<TextField source="id" />
<NumberField source="active" />
<NumberField source="time" />
<DateField source="createdAt" />
<DateField source="updatedAt" />
<ReferenceField source="UserId" reference="Users">
<TextField source="name" />
</ReferenceField>
<ReferenceField source="ToolId" reference="Tools">
<TextField source="code" />
</ReferenceField>
</Datagrid>
</List>
);
I also find out that if i try to inspect ReferenceField element with react-dev-tool, There are no values but just "Loading..." note. But I dont know why... It looks to me that API response is OK.
API res: Btools fetch:
(2) [{…}, {…}]
0:
ToolId: 1
UserId: 1
active: 1
createdAt: "2020-04-08T16:00:03.000Z"
id: 1
time: 1
updatedAt: "2020-04-08T16:00:03.000Z"
__proto__: Object
1:
ToolId: 1
UserId: 2
active: 1
createdAt: "2020-04-08T16:00:03.000Z"
id: 2
time: 1
updatedAt: "2020-04-08T16:00:03.000Z"
__proto__: Object
length: 2
__proto__: Array(0)
Than Users and Tools fetch:
(2) [{…}, {…}]
0: {id: 1, name: "Tomáš Princ", email: "p***@seznam.cz", createdAt: "2020-04-08T15:59:54.000Z", updatedAt: "2020-04-08T15:59:54.000Z"}
1: {id: 2, name: "jhfgjhfg", email: "admin@admin.cz", createdAt: "2020-04-08T18:44:16.000Z", updatedAt: "2020-04-08T18:44:16.000Z"}
length: 2
__proto__: Array(0)
[{…}]
0: {id: 1, code: "guhf", name: "jhfh", state: "ghf", free: 1, …}
length: 1
__proto__: Array(0)
I log this json data in DataProvider and return it like data: json
switch (type) {
case GET_LIST:
case GET_MANY:
case GET_MANY_REFERENCE:
console.log(json)
console.log(type)
if (!headers.has('content-range')) {
throw new Error(
'The Content-Range header is missing in the HTTP Response. The simple REST data provider 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?'
);
}
console.log((headers.get('content-range')))
return {
data: json,
total:
//json.length,
parseInt(
headers
.get('content-range')
.split('/')
.pop(),
10
),
};
So it look like app have all data it needs, but for some reason still loading and waiting for something.
EDIT 2: I tried little workaround by creating custom element, that load userId and toolId and fetches classic query get user/tool by ID for every row. It works.
const ToolCode = ({ record = {} }) => {
const dataProvider = useDataProvider();
const [tool, setTool] = useState();
const [loading, setLoading] = useState(true);
const [error, setError] = useState();
useEffect(() => {
dataProvider.getOne('tools', { id: record.ToolId })
.then(({ data }) => {
setTool(data);
setLoading(false);
})
.catch(error => {
setError(error);
setLoading(false);
})
}, []);
if (loading) return <Loading />;
if (error) return <Error />;
if (!tool) return null;
console.log("fetch tools")
return (
tool.code
)
};
const UserName = ({ record = {} }) => {
const dataProvider = useDataProvider();
const [user, setUser] = useState();
const [loading, setLoading] = useState(true);
const [error, setError] = useState();
useEffect(() => {
dataProvider.getOne('users', { id: record.UserId })
.then(({ data }) => {
setUser(data);
setLoading(false);
})
.catch(error => {
setError(error);
setLoading(false);
})
}, []);
if (loading) return <Loading />;
if (error) return <Error />;
if (!user) return null;
return (
user.name
)
};
const B_toolFilter = (props) => (
<Filter {...props}>
<TextInput label="Search" source="q" alwaysOn />
<TextInput label="Title" source="title" defaultValue="Hello, World!" />
</Filter>
);
export const B_toolList = props => (
<List {...props}>
<Datagrid rowClick="edit">
<TextField source="id" />
<NumberField source="active" />
<NumberField source="time" />
<DateField source="createdAt" />
<DateField source="updatedAt" />
<UserName source="UserId" />
<ToolCode source="ToolId" />
</Datagrid>
</List>
);
Now I can get tool code and user name by IDs form B_Tools, but its much less efficient than GET_MANY method used by ReferenceField..