T
TanStack•2y ago
other-emerald

Suggestion for accessing useQuery data

Context: We are looking forward to migrate our async data handling layer of useContext + useReducer to react-query. Currently we are in react v17 which means we have use react-query v4 We have an page which has header section (with high level info) and side tabs. Each tab will have multiple api calls (both parallel and dependent ones) and also multiple components which might only interest in specific data from specific api. Idea is to fetch all api data in the root of the specific tab's parent which handles both loading and error scenario and then let child component access data without prob drilling and using select to only re-render on specific data change. One of the concern is type of data having TData | undefined which forces us to ! . I was looking over internet for different options, these are something i found or came up with 1. Going ahead with ! Concern: The quality of the code.
const TodoName = () => {
const {data} = useTodo('2', (todo: ITodo) => todo.name);

const name: string = data!;

return <p>Todo: {name}</p>
}
const TodoName = () => {
const {data} = useTodo('2', (todo: ITodo) => todo.name);

const name: string = data!;

return <p>Todo: {name}</p>
}
2. using useSuspenseQuery to access in child components and parent to use useQuery for initial fetching. So we can handle api specific loading and error scenarios in parent and child can access data without concern. Concern: We can't use this as we are at react-query v4 and also not sure does it has any pitfalls 😦
const useTodo = <T = ITodo, >(id: string, select?: (data: ITodo) => T) =>
useQuery(getTodoQueryOptions(id, select));

const useTodoData = <T = ITodo, >(id: string, select?: (data: ITodo) => T) =>
useSuspenseQuery(getTodoQueryOptions(id, select));
const useTodo = <T = ITodo, >(id: string, select?: (data: ITodo) => T) =>
useQuery(getTodoQueryOptions(id, select));

const useTodoData = <T = ITodo, >(id: string, select?: (data: ITodo) => T) =>
useSuspenseQuery(getTodoQueryOptions(id, select));
1 Reply
other-emerald
other-emeraldOP•2y ago
3. using react context to pass data to children (refering: https://tkdodo.eu/blog/react-query-and-react-context). It solves both data type issue and also prob drilling. Concerns: Not sure how to make use of the select behaviour and we need other info such as isError for specific api (Not sure how this approach will look with multiple api) 4. using custom hook for accessing data (inspired by useSuspenseQuery) Concerns: Not sure does it has any pitfalls 😦
const useQueryData = <TData, TError>(query: UseQueryResult<TData, TError>) => {
return query as UseQueryResult<TData, TError> & { data: TData };
}

const TodoName = () => {
const {data: name} = useQueryData(useTodo('2', (todo: ITodo) => todo.name));

return <p>Todo: {name}</p>
}
const useQueryData = <TData, TError>(query: UseQueryResult<TData, TError>) => {
return query as UseQueryResult<TData, TError> & { data: TData };
}

const TodoName = () => {
const {data: name} = useQueryData(useTodo('2', (todo: ITodo) => todo.name));

return <p>Todo: {name}</p>
}
Look forward to hear the suggestion from community on the options. (Thinking of going with custom hook incase we are have to go with react-query v4. If we are able to migrate to v5 then option 2 of using useSuspenseQuery for accessing data)

Did you find this page helpful?