T
TanStack•4y ago
vicious-gold

Filtering through returned data

Where should I be filtering through the data, what's best practice? Would it be onSuccess? At the moment I am doing it like this:
export const fetchEmployers = () => {
const platformEmployerTypes = [1, 3];

return useQuery(["fetchEmployers"],
async () => {
const { data } = await axios({
url: foo,
method: "get"
});
return data.filter((item) => platformEmployerTypes.includes(item.type));
}
);
};
export const fetchEmployers = () => {
const platformEmployerTypes = [1, 3];

return useQuery(["fetchEmployers"],
async () => {
const { data } = await axios({
url: foo,
method: "get"
});
return data.filter((item) => platformEmployerTypes.includes(item.type));
}
);
};
18 Replies
ambitious-aqua
ambitious-aqua•4y ago
Hi, it all depends on what data you would like to cache, how your API allows you to filter etc. With the code above, the data that would be cached would be the filtered one another solution You retrieve all your employers and you define 2 hooks: one to retrieve all employers, another one which uses the same queryKey with a select to apply the filters.
vicious-gold
vicious-goldOP•4y ago
Ok, I will investigate, thanks for the reply 🙂
ambitious-aqua
ambitious-aqua•4y ago
Don't forget to read https://tkdodo.eu/blog/react-query-data-transformations while investigating 😉
React Query Data Transformations
Learn the possibilities to perform the quite common and important task of transforming your data with react-query
vicious-gold
vicious-goldOP•4y ago
Taking into consideration that if I do the filtering in the fetchEmployers useQuery, it kinda defeats the hooks re-usablility. So my naive approach is to filter through the data in the component instead.
const Component = () => {
const { data } = fetchEmployers();

const platformEmployerTypes = [1, 3];

const employersData = data?.filter((item) => platformEmployerTypes.includes(item.type));
...
const Component = () => {
const { data } = fetchEmployers();

const platformEmployerTypes = [1, 3];

const employersData = data?.filter((item) => platformEmployerTypes.includes(item.type));
...
I will have a read of the docs on how to use select`to replicate Or, I can create a new hook with select and call that in the component, so we have 2 hooks. 1 to fetch the Employers which we can re-use. another hook to do the filtering.
export const fetchEmployers = () => {
return useQuery([employers.fetchEmployers],
async () => {
const { data } = await axios({
url: foo,
method: "get"
});
return data;
}
);
};

export const fetchEmployersQuery = () => {
const platformEmployerTypes = [1, 3];

return useQuery([employers.fetchEmployers],
async () => {
const { data } = await axios({
url: foo,
method: "get"
});
return data;
},
{
select: (data) => data.filter((item) => platformEmployerTypes.includes(item.type))
}
);
};
export const fetchEmployers = () => {
return useQuery([employers.fetchEmployers],
async () => {
const { data } = await axios({
url: foo,
method: "get"
});
return data;
}
);
};

export const fetchEmployersQuery = () => {
const platformEmployerTypes = [1, 3];

return useQuery([employers.fetchEmployers],
async () => {
const { data } = await axios({
url: foo,
method: "get"
});
return data;
},
{
select: (data) => data.filter((item) => platformEmployerTypes.includes(item.type))
}
);
};
ambitious-aqua
ambitious-aqua•4y ago
You should also rename your hooks prefix them with use
vicious-gold
vicious-goldOP•4y ago
Good point. Thanks 🙂
ambitious-aqua
ambitious-aqua•4y ago
Also you could factorise the query config (queryKey, queryFn) between the 2 hooks to make sure they stay in sync
vicious-gold
vicious-goldOP•4y ago
Where is a typical place you would store the queryFn's? For example, in another file in utils?
ambitious-aqua
ambitious-aqua•4y ago
"it depends"
ambitious-aqua
ambitious-aqua•4y ago
We took inspiration from https://tkdodo.eu/blog/effective-react-query-keys to build our own key factories
Effective React Query Keys
Learn how to structure React Query Keys effectively as your App grows
vicious-gold
vicious-goldOP•4y ago
I want to re-use the queryFn's but run into an error that I can't seem to workout. fetchEmployees is the queryFn that is used in both useFetchEmployers and useFetchEmployersQuery. This makes sense to me and should work but I get the the below error. Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: Not sure if I am missing something obvious?
const fetchEmployees = async () => {
const { data } = await axios({
url: foo,
method: "get"
});
return data;
};

export const useFetchEmployers = () => {
return useQuery([employers.fetchEmployers], fetchEmployees);
};

export const useFetchEmployersQuery = () => {
const platformEmployerTypes = [1, 3];

return useQuery([employers.fetchEmployers], fetchEmployees,
{
select: (data) => data.filter((item) => platformEmployerTypes.includes(item.type))
}
);
};
const fetchEmployees = async () => {
const { data } = await axios({
url: foo,
method: "get"
});
return data;
};

export const useFetchEmployers = () => {
return useQuery([employers.fetchEmployers], fetchEmployees);
};

export const useFetchEmployersQuery = () => {
const platformEmployerTypes = [1, 3];

return useQuery([employers.fetchEmployers], fetchEmployees,
{
select: (data) => data.filter((item) => platformEmployerTypes.includes(item.type))
}
);
};
const { data: employersData } = useFetchEmployersQuery();
const { data: employersData } = useFetchEmployersQuery();
ambitious-aqua
ambitious-aqua•4y ago
Is this used in a component ? I mean this line: const { data: employersData } = useFetchEmployersQuery();
vicious-gold
vicious-goldOP•4y ago
Yep
ambitious-aqua
ambitious-aqua•4y ago
hum strange Could you provide more code sample to help understanding ?
vicious-gold
vicious-goldOP•4y ago
Sure. Component:
import React from "react";
import { useFetchEmployersQuery } from "./teamsHooks";

const Teams = () => {
const { data: employersData } = useFetchEmployersQuery();

return (
<div className="content">

<EmployersGrid
employersData={employersData}
/>
</div>
);
};

export default Teams;
import React from "react";
import { useFetchEmployersQuery } from "./teamsHooks";

const Teams = () => {
const { data: employersData } = useFetchEmployersQuery();

return (
<div className="content">

<EmployersGrid
employersData={employersData}
/>
</div>
);
};

export default Teams;
Hook File
import { useQuery, useMutation } from "react-query";

import { employers } from "../../utils/queryKeys";

import axios from "axios";

const fetchEmployees = async () => {
const { data } = await axios({
url: foo,
method: "get"
});
return data;
};

export const useFetchEmployers = () => {
return useQuery([employers.fetchEmployers], fetchEmployees);
};

export const useFetchEmployersQuery = () => {
const platformEmployerTypes = [1, 3];

return useQuery([employers.fetchEmployers], fetchEmployees,
{
select: (data) => data.filter((item) => platformEmployerTypes.includes(item.type))
}
);
};
import { useQuery, useMutation } from "react-query";

import { employers } from "../../utils/queryKeys";

import axios from "axios";

const fetchEmployees = async () => {
const { data } = await axios({
url: foo,
method: "get"
});
return data;
};

export const useFetchEmployers = () => {
return useQuery([employers.fetchEmployers], fetchEmployees);
};

export const useFetchEmployersQuery = () => {
const platformEmployerTypes = [1, 3];

return useQuery([employers.fetchEmployers], fetchEmployees,
{
select: (data) => data.filter((item) => platformEmployerTypes.includes(item.type))
}
);
};
ambitious-aqua
ambitious-aqua•4y ago
Strange
vicious-gold
vicious-goldOP•4y ago
Yeah, can't work it out
ambitious-aqua
ambitious-aqua•4y ago
Could you try reproducing in a codesandbox?

Did you find this page helpful?