fair-rose
fair-rose5d ago

Query Multiple Resources at Once

Is it possible to query multiple tables at once in order to avoid potential side-effects with different number of renders and improve efficiency? See:
const { dataGridProps } = useDataGrid();

const resources = supabaseColumns
.filter((column) => column.foreign_key_reference)
.map(({ column_name }) => `${column_name.split("_")[0]}s`);


// TODO: How to pass resources which is an array of resource to query
// multiple table at once.
// const { data: records, isLoading } = useMany({});
const { dataGridProps } = useDataGrid();

const resources = supabaseColumns
.filter((column) => column.foreign_key_reference)
.map(({ column_name }) => `${column_name.split("_")[0]}s`);


// TODO: How to pass resources which is an array of resource to query
// multiple table at once.
// const { data: records, isLoading } = useMany({});
5 Replies
kapa.ai
kapa.ai5d ago
Hi @dionysos6378. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To query multiple resources at once in refine, you can use the useMany hook with parallel queries. Here's how you can modify your code to achieve this:
import { useMany } from "@refinedev/core";

const { dataGridProps } = useDataGrid();

const resources = supabaseColumns
.filter((column) => column.foreign_key_reference)
.map(({ column_name }) => `${column_name.split("_")[0]}s`);

const queries = resources.map(resource => ({
resource,
ids: dataGridProps.rows.map(row => row[`${resource.slice(0, -1)}_id`])
}));

const results = useMany({
queries,
queryOptions: {
enabled: queries.length > 0 && dataGridProps.rows.length > 0,
},
});
import { useMany } from "@refinedev/core";

const { dataGridProps } = useDataGrid();

const resources = supabaseColumns
.filter((column) => column.foreign_key_reference)
.map(({ column_name }) => `${column_name.split("_")[0]}s`);

const queries = resources.map(resource => ({
resource,
ids: dataGridProps.rows.map(row => row[`${resource.slice(0, -1)}_id`])
}));

const results = useMany({
queries,
queryOptions: {
enabled: queries.length > 0 && dataGridProps.rows.length > 0,
},
});
This approach uses the useMany hook to fetch data from multiple resources in parallel. Here's how it works: 1. We create an array of query objects, one for each resource we want to fetch. 2. Each query object specifies the resource name and the ids to fetch from that resource. 3. We pass this array of queries to the useMany hook. The useMany hook will execute these queries in parallel, improving efficiency and avoiding multiple renders useMany hook (https://refine.dev/docs/data/hooks/use-many/). Note that this approach assumes that your data structure follows a certain pattern (e.g., foreign keys are named as resource_id). You might need to adjust the id mapping based on your specific data structure. Also, make sure that your data provider supports the getMany method for optimal performance. If it doesn't, useMany will fall back to using getOne for each id, which could be less efficient useMany documentation (https://refine.dev/docs/data/hooks/use-many/). Remember to handle the loading state and potential errors in your component:
if (results.some(result => result.isLoading)) {
return <div>Loading...</div>;
}
if (results.some(result => result.isError)) {
return <div>Error occurred while fetching data</div>;
}

// Use the data from results here
if (results.some(result => result.isLoading)) {
return <div>Loading...</div>;
}
if (results.some(result => result.isError)) {
return <div>Error occurred while fetching data</div>;
}

// Use the data from results here
This approach should allow you to query multiple resources at once, improving efficiency and reducing the number of renders. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@841352460907708447> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
fair-rose
fair-roseOP5d ago
@kapa.ai I am now getting:
const supabaseColumns = useSupabaseColumns(resource.identifier);
const apiRef = useGridApiRef();
const { dataGridProps } = useDataGrid();

const [queries, setQueries] = useState([{}]);

useEffect(() => {
const resources = supabaseColumns
.filter((column) => column.foreign_key_reference)
.map(({ column_name }) => `${column_name.split("_")[0]}s`);

const queries = resources.map((resource) => {
const supabaseColumn = `${resource.slice(0, -1)}_id`;
return {
resource,
ids: dataGridProps.rows.map((row) => row[supabaseColumn]),
};
});

setQueries(queries);
}, [supabaseColumns]);

const { data } = useMany({
queries,
queryOptions: {
enabled: queries.length > 0 && dataGridProps.rows.length > 0,
},
});
const supabaseColumns = useSupabaseColumns(resource.identifier);
const apiRef = useGridApiRef();
const { dataGridProps } = useDataGrid();

const [queries, setQueries] = useState([{}]);

useEffect(() => {
const resources = supabaseColumns
.filter((column) => column.foreign_key_reference)
.map(({ column_name }) => `${column_name.split("_")[0]}s`);

const queries = resources.map((resource) => {
const supabaseColumn = `${resource.slice(0, -1)}_id`;
return {
resource,
ids: dataGridProps.rows.map((row) => row[supabaseColumn]),
};
});

setQueries(queries);
}, [supabaseColumns]);

const { data } = useMany({
queries,
queryOptions: {
enabled: queries.length > 0 && dataGridProps.rows.length > 0,
},
});
Unexpected Application Error!
t is not iterable (cannot read property undefined)
TypeError: t is not iterable (cannot read property undefined)
at useMany (http://localhost:8888/node_modules/.vite/deps/chunk-CREVPCSZ.js?v=a7dc3742:9114:75)
at DataGridView (http://localhost:8888/src/views/private/DataGridView.jsx?t=1730552937420:42:22)
at renderWithHooks (http://localhost:8888/node_modules/.vite/deps/chunk-RY6NLCXT.js?v=a7dc3742:11548:26)
at mountIndeterminateComponent (http://localhost:8888/node_modules/.vite/deps/chunk-RY6NLCXT.js?v=a7dc3742:14926:21)
at beginWork (http://localhost:8888/node_modules/.vite/deps/chunk-RY6NLCXT.js?v=a7dc3742:15914:22)
...
Unexpected Application Error!
t is not iterable (cannot read property undefined)
TypeError: t is not iterable (cannot read property undefined)
at useMany (http://localhost:8888/node_modules/.vite/deps/chunk-CREVPCSZ.js?v=a7dc3742:9114:75)
at DataGridView (http://localhost:8888/src/views/private/DataGridView.jsx?t=1730552937420:42:22)
at renderWithHooks (http://localhost:8888/node_modules/.vite/deps/chunk-RY6NLCXT.js?v=a7dc3742:11548:26)
at mountIndeterminateComponent (http://localhost:8888/node_modules/.vite/deps/chunk-RY6NLCXT.js?v=a7dc3742:14926:21)
at beginWork (http://localhost:8888/node_modules/.vite/deps/chunk-RY6NLCXT.js?v=a7dc3742:15914:22)
...
kapa.ai
kapa.ai5d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I apologize for the confusion in my previous answer. The error you're encountering suggests that there's an issue with how the useMany hook is being used. Let's modify the code to address this problem:
import { useMany } from "@refinedev/core";
import { useState, useEffect } from "react";

const DataGridView = () => {
const supabaseColumns = useSupabaseColumns(resource.identifier);
const apiRef = useGridApiRef();
const { dataGridProps } = useDataGrid();

const [queries, setQueries] = useState([]);

useEffect(() => {
if (dataGridProps.rows && dataGridProps.rows.length > 0) {
const resources = supabaseColumns
.filter((column) => column.foreign_key_reference)
.map(({ column_name }) => `${column_name.split("_")[0]}s`);

const newQueries = resources.map((resource) => {
const supabaseColumn = `${resource.slice(0, -1)}_id`;
return {
resource,
ids: dataGridProps.rows
.map((row) => row[supabaseColumn])
.filter((id) => id !== undefined && id !== null),
};
}).filter((query) => query.ids.length > 0);

setQueries(newQueries);
}
}, [supabaseColumns, dataGridProps.rows]);

const { data, isLoading } = useMany({
queries,
queryOptions: {
enabled: queries.length > 0,
},
});

if (isLoading) {
return <div>Loading...</div>;
}

// Rest of your component code
};
import { useMany } from "@refinedev/core";
import { useState, useEffect } from "react";

const DataGridView = () => {
const supabaseColumns = useSupabaseColumns(resource.identifier);
const apiRef = useGridApiRef();
const { dataGridProps } = useDataGrid();

const [queries, setQueries] = useState([]);

useEffect(() => {
if (dataGridProps.rows && dataGridProps.rows.length > 0) {
const resources = supabaseColumns
.filter((column) => column.foreign_key_reference)
.map(({ column_name }) => `${column_name.split("_")[0]}s`);

const newQueries = resources.map((resource) => {
const supabaseColumn = `${resource.slice(0, -1)}_id`;
return {
resource,
ids: dataGridProps.rows
.map((row) => row[supabaseColumn])
.filter((id) => id !== undefined && id !== null),
};
}).filter((query) => query.ids.length > 0);

setQueries(newQueries);
}
}, [supabaseColumns, dataGridProps.rows]);

const { data, isLoading } = useMany({
queries,
queryOptions: {
enabled: queries.length > 0,
},
});

if (isLoading) {
return <div>Loading...</div>;
}

// Rest of your component code
};
Here are the key changes and explanations: 1. We initialize queries state as an empty array instead of an object. 2. In the useEffect, we now check if dataGridProps.rows exists and has length before processing. 3. We filter out any undefined or null ids when creating the ids array for each query. 4. We filter out any queries that end up with empty ids arrays. 5. We've moved the enabled condition to only depend on queries.length > 0, as the dataGridProps.rows.length check is now handled in the useEffect. 6. We're now destructuring isLoading from the useMany hook to handle the loading state. This approach should resolve the "t is not iterable" error you were encountering. The error was likely caused by trying to iterate over undefined or null values in the ids array. Remember, the useMany hook in refine expects an array of query objects, each with a resource and ids property useMany hook (https://refine.dev/docs/data/hooks/use-many/). By ensuring that we only pass valid queries with non-empty ids arrays, we should avoid the iteration error. If you're still encountering issues, please double-check that your dataGridProps.rows is populated correctly and that the foreign key columns in your data match the expected format (resource_id). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@841352460907708447> Kapa.ai is still learning and improving, please let me know how I did by reacting below.