Jun 17, 2020 07:30 AM
I’m building a block which (should) allow users to select multiple records in Table A. I would like to get a set of each selected record’s linked Table B records. The problem I’m running in to I believe relates to using a hook within a loop.
Right now I’m using selectedRecords.map(record => {...} ).flat()
to loop through each selected record. Within the loop, I’m using useRecords(record.selectLinkedRecordsFromCell(fieldName))
to get the linked records into a single array. This works but only if the user selects the same number of records each time, or cancels the current selection and starts over. Meaning if someone selects one record it works, if someone selects all records it works, but if someone changes the number of selected records by clicking and dragging or by using the selection boxes at the far left, React throws an error: Error: Rendered more/fewer hooks than during the previous render.
I think I could possible get around this if I could combine/collapse multiple record query results into one, then I’d only have to use useRecords()
in one place and it could be a top level step. Is this possible? If not, is there some other workaround to get past this issue?
Solved! Go to Solution.
Jun 17, 2020 08:12 AM
Hi Kamille!
Under the hood, all that useRecords
does is something like this:
useLoadable(query);
useWatchable(query, ['records', 'cellValues', 'recordColors']);
return query.records;
(it’s actually a little more complicated than that, but that’s the essence of it - you can check out the source code here if you’re interested!)
Whilst useRecords
only accepts a single query/table/view etc, the lower-level useLoadable
and useWatchable
hooks accept arrays. That means you could do something like this:
// get linked record queries for every record:
const linkedRecordQueries = selectedRecords.map(
record => record.selectLinkedRecordsFromCell(fieldName),
);
// load all the linked record queries:
useLoadable(linkedRecordQueries);
// rerender whenever any of the records in those queries change:
useWatchable(linkedRecordQueries, ['records', 'cellValues', 'recordColors']);
// get one big array with all the linked records:
const allLinkedRecords = linkedRecordQueries
.map(query => query.records)
.flat();
Creating lots of query results very dynamically like this though probably won’t be great for performance on large tables though.
Relevant docs links:
Hope this helps!
Jun 17, 2020 08:12 AM
Hi Kamille!
Under the hood, all that useRecords
does is something like this:
useLoadable(query);
useWatchable(query, ['records', 'cellValues', 'recordColors']);
return query.records;
(it’s actually a little more complicated than that, but that’s the essence of it - you can check out the source code here if you’re interested!)
Whilst useRecords
only accepts a single query/table/view etc, the lower-level useLoadable
and useWatchable
hooks accept arrays. That means you could do something like this:
// get linked record queries for every record:
const linkedRecordQueries = selectedRecords.map(
record => record.selectLinkedRecordsFromCell(fieldName),
);
// load all the linked record queries:
useLoadable(linkedRecordQueries);
// rerender whenever any of the records in those queries change:
useWatchable(linkedRecordQueries, ['records', 'cellValues', 'recordColors']);
// get one big array with all the linked records:
const allLinkedRecords = linkedRecordQueries
.map(query => query.records)
.flat();
Creating lots of query results very dynamically like this though probably won’t be great for performance on large tables though.
Relevant docs links:
Hope this helps!
Jun 17, 2020 08:49 AM
Thank you!! for both the quick response and the warning of performance.