질의 함수 컨텍스트 사용
26078 단어 webdevreactjavascripttypescript
처음 React Query를 사용하기 시작한 이후 상당한 시간이 흘렀습니다.나는 그 여행에서 많은 것을 배웠고, 나도 많은 것을 보았다고 생각한다.나는 나의 블로그가 가능한 한 갱신되기를 바란다. 이렇게 하면 너는 이곳으로 돌아가서 다시 읽을 수 있고, 이러한 개념들이 여전히 유효하다는 것을 알게 될 것이다.공식 홈페이지React Query documentation에서 제 블로그에 링크하는 것에 동의한 후 그 어느 때보다도 관련이 있습니다.
이것이 바로 내가 이 문장의 부록을 쓰기로 결정한 이유다.우리가 이야기하고 있는 내용을 이해하기 위해서 반드시 먼저 읽어 주십시오.
인기 상품
Don't use inline functions - leverage the Query Function Context given to you, and use a Query Key factory that produces object keys
지금까지 내연 함수는queryFn에 매개 변수를 전달하는 가장 간단한 방법입니다. 사용자 정의 갈고리의 다른 변수에 패키지를 닫을 수 있기 때문입니다.상청todo의 예를 살펴보자.
type State = 'all' | 'open' | 'done'
type Todo = {
id: number
state: TodoState
}
type Todos = ReadonlyArray<Todo>
const fetchTodos = async (state: State): Promise<Todos> => {
const response = await axios.get(`todos/${state}`)
return response.data
}
export const useTodos = () => {
// imagine this grabs the current user selection
// from somewhere, e.g. the url
const { state } = useTodoParams()
// ✅ The queryFn is an inline function that
// closures over the passed state
return useQuery(['todos', state], () => fetchTodos(state))
}
아마도 너는 이 예를 알고 있을 것이다. 그것은 #1: Practical React Query - Treat the query key like a dependency array의 작은 변화이다.이것은 간단한 예에 매우 효과가 있지만, 많은 매개 변수가 있을 때, 그것은 상당히 큰 문제가 있다.더 큰 프로그램에서, 많은 필터와 정렬 옵션이 듣지 못했던 것이 아니라, 나는 개인적으로 10개의 파라미터가 전달되는 것을 보았다.검색에 정렬을 추가하고 싶다고 가정하십시오.나는 이 일들을 아래에서 위로 처리하는 것을 좋아한다.queryFn에서부터 컴파일러가 다음에 무엇을 변경해야 하는지 알려주도록 한다.
type Sorting = 'dateCreated' | 'name'
const fetchTodos = async (
state: State,
sorting: Sorting
): Promise<Todos> => {
const response = await axios.get(`todos/${state}?sorting=${sorting}`)
return response.data
}
이것은 틀림없이 우리의 사용자 정의 갈고리에 오류가 발생할 것입니다.fetchTodos를 호출했기 때문에 복구합니다.export const useTodos = () => {
const { state, sorting } = useTodoParams()
// 🚨 can you spot the mistake ⬇️
return useQuery(['todos', state], () => fetchTodos(state, sorting))
}
아마도 너는 이미 이 문제를 발견했을 것이다. 우리의query Key는 우리의 실제 의존항과 동기화되지 않고, 붉은 곡선이 우리를 향해 비명을 지르지 않았다😔. 상기 상황에서, 당신은 문제를 곧 발견할 수 있습니다. (통합 테스트를 통과하기를 희망합니다.) 정렬을 변경하면 자동으로 재식각을 촉발하지 않기 때문입니다.솔직히 이 간단한 예에서도 뚜렷하다.그러나 지난 몇 달 동안queryKey와 실제 의존 관계에 몇 차례의 불일치가 발생했고 복잡성이 증가함에 따라 추적하기 어려운 문제가 발생할 수 있음을 보았다.리액트 동봉react-hooks/exhaustive-deps eslint rule도 이런 상황을 피하기 위해서다.따라서, React 조회는 현재 자신의 eslint 규칙이 있습니까?👀 ?
그것은 선택이다.그리고 babel-plugin-react-query-key-gen
이 문제를 해결하기 위해 검색 키 (모든 의존항 포함) 를 생성합니다.그러나React 조회는 서로 다른 내장된 처리 의존 관계를 제공하는 방법인React
QueryFunctionContext
을 제공했다.QueryFunctionContext
QueryFunctionContext는queryFn에 매개 변수로 전달되는 객체입니다.이전에 무한 질의를 처리할 때 사용한 적이 있을 수 있습니다.
// this is the QueryFunctionContext ⬇️
const fetchProjects = ({ pageParam = 0 }) =>
fetch('/api/projects?cursor=' + pageParam)
useInfiniteQuery('projects', fetchProjects, {
getNextPageParam: (lastPage) => lastPage.nextCursor,
})
React Query 를 사용하여 질의에 대한 정보를query Fn에 주입합니다.무한 조회의 경우, 페이지 페이지에 주입된 getNextPageParam의 반환 값을 받을 수 있습니다.그러나 컨텍스트에는 이 질의에 사용되는query Key(컨텍스트에 더 멋진 컨텐트를 추가함)가 포함되어 있으므로 실제로 컨텐트를 클로즈업할 필요가 없습니다. React query가 이러한 컨텐트를 제공하기 때문입니다.
const fetchTodos = async ({ queryKey }) => {
// 🚀 we can get all params from the queryKey
const [, state, sorting] = queryKey
const response = await axios.get(`todos/${state}?sorting=${sorting}`)
return response.data
}
export const useTodos = () => {
const { state, sorting } = useTodoParams()
// ✅ no need to pass parameters manually
return useQuery(['todos', state, sorting], fetchTodos)
}
이 방법을 사용하면,query Key에 추가하지 않고query Fn에 추가 인자를 사용할 수 없습니다.🎉.QueryFunctionContext 입력 방법
이러한 방법의 목표 중 하나는 완전한 유형 안전성을 얻고useQuery에 전달되는queryKey에서QueryFunctionContext의 유형을 추정하는 것이다.쉽지 않지만 React Query는 v3.13.3 때문에 이를 지원합니다.내연queryFn을 사용하면 형식이 정확하게 추정되는 것을 볼 수 있습니다. (감사합니다. 일반)
export const useTodos = () => {
const { state, sorting } = useTodoParams()
return useQuery(
['todos', state, sorting] as const,
async ({ queryKey }) => {
const response = await axios.get(
// ✅ this is safe because the queryKey is a tuple
`todos/${queryKey[1]}?sorting=${queryKey[2]}`
)
return response.data
}
)
}
이 모든 것은 매우 좋으나, 여전히 약간의 결함이 있다.중점 공장을 조회하다.
이것이 바로 관건적인 공장이 다시 나타난 곳이다.만약 우리가 안전한 검색 키 공장을 가지고 키를 구축한다면, 이 공장의 되돌아오는 형식을 사용하여QueryFunctionContext를 입력할 수 있습니다.가능한 경우는 다음과 같습니다.
const todoKeys = {
all: ['todos'] as const,
lists: () => [...todoKeys.all, 'list'] as const,
list: (state: State, sorting: Sorting) =>
[...todoKeys.lists(), state, sorting] as const,
}
const fetchTodos = async ({
queryKey,
}: // 🤯 only accept keys that come from the factory
QueryFunctionContext<ReturnType<typeof todoKeys['list']>>) => {
const [, , state, sorting] = queryKey
const response = await axios.get(`todos/${state}?sorting=${sorting}`)
return response.data
}
export const useTodos = () => {
const { state, sorting } = useTodoParams()
// ✅ build the key via the factory
return useQuery(todoKeys.list(state, sorting), fetchTodos)
}
유형QueryFunctionContext는 React Query에서 내보냅니다.query Key의 유형을 정의하는 범용이 필요합니다.위의 예시에서, 우리는 그것을 키 공장의list 함수와 같은 값으로 설정했다.우리가 사용하기 때문에 const assertions 모든 키는 엄격하게 유형화된 원조이기 때문에, 이 구조에 맞지 않는 키를 사용하려고 하면 유형 오류가 발생할 수 있습니다.객체 조회 키
상술한 방법으로 천천히 넘어갈 때, 나는 수조 키의 성능이 결코 좋지 않다는 것을 알아차렸다.이제 Query 키를 제거하는 방법을 살펴보면 다음과 같습니다.
const [, , state, sorting] = queryKey
우리는 기본적으로 앞의 두 부분을 생략하고 동적 부분만 사용합니다.물론 얼마 지나지 않아 우리는 처음부터 다른 역할 영역을 추가했고 이로 인해 잘못된 URL이 만들어졌다.Source: A PR I recently made
명명의 분해를 사용할 수 있기 때문에 대상이 이 문제를 잘 해결했다는 사실이 증명되었다.또한 쿼리 키에서 사용할 때, 쿼리의 잘못된 모호한 일치가 대상과 그룹에 대한 효과가 같기 때문에 단점이 없습니다.partialDeepEqual 함수의 작업 원리에 관심이 있다면 그것을 보십시오.
이 점을 기억하라. 이것이 바로 내가 오늘 알고 있는 조회 키를 구성하는 방법이다.
const todoKeys = {
// ✅ all keys are arrays with exactly one object
all: [{ scope: 'todos' }] as const,
lists: () => [{ ...todoKeys.all[0], entity: 'list' }] as const,
list: (state: State, sorting: Sorting) =>
[{ ...todoKeys.lists()[0], state, sorting }] as const,
}
const fetchTodos = async ({
// ✅ extract named properties from the queryKey
queryKey: [{ state, sorting }],
}: QueryFunctionContext<ReturnType<typeof todoKeys['list']>>) => {
const response = await axios.get(`todos/${state}?sorting=${sorting}`)
return response.data
}
export const useTodos = () => {
const { state, sorting } = useTodoParams()
return useQuery(todoKeys.list(state, sorting), fetchTodos)
}
대상 조회 키는 순서가 없기 때문에 모호한 일치 기능을 더욱 강하게 한다.수조 방법을 사용하면 모든 업무, 모든 업무 목록을 처리하거나, 특정한 필터를 사용하여 업무 목록을 처리할 수 있습니다.객체 키를 사용하여 다음을 수행할 수도 있습니다.// 🕺 remove everything related to the todos feature
queryClient.removeQueries([{ scope: 'todos' }])
// 🚀 reset all todo lists
queryClient.resetQueries([{ scope: 'todos', entity: 'list' }])
// 🙌 invalidate all lists across all scopes
queryClient.invalidateQueries([{ entity: 'list' }])
만약 차원 구조를 가진 중첩작용역이 여러 개 있지만, 하위 작용역에 속하는 모든 내용을 일치시키기를 원한다면, 이것은 매우 유용할 것입니다.이게 가치가 있습니까?
여느 때와 다름없다: 상황을 보고 결정한다.나는 최근에 줄곧 이런 방법을 매우 좋아해 왔지만, 복잡성과 유형 안전 사이에는 틀림없이 절충이 있을 것이다.키 공장에서 검색 키를 조합하는 것은 약간 복잡하다. (querykey는 여전히 맨 윗부분의 그룹이어야 하기 때문에) 키 공장의 되돌아오는 형식에 따라 상하문을 입력하는 것도 간단하지 않다.만약 팀의 규모가 작고api 인터페이스가 얇으며/또는 순수한 자바스크립트를 사용한다면, 이 길을 걷고 싶지 않을 수도 있습니다.관례에 따라 너의 구체적인 상황에 가장 의미 있는 도구와 방법을 선택하다🙌
오늘은 여기까지.언제든지 연락 주세요.
만약 당신에게 어떤 문제가 있거나, 아래에 평론을 남겨라⬇️
Reference
이 문제에 관하여(질의 함수 컨텍스트 사용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/tkdodo/leveraging-the-query-function-context-3i72텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)