질의 함수 컨텍스트 사용

엔지니어로서, 우리는 모두 향상시키려고 노력하고 있으며, 시간의 추이에 따라, 우리는 이 방면에서 성공을 거두기를 희망한다.아마도 우리가 배운 새로운 것이 이전의 생각을 실효시키거나 도전을 받게 할 것이다.혹은 우리는 이상적인 모델이 현재 우리가 필요로 하는 수준으로 확대될 수 없다고 생각하는 것을 깨달았다.
처음 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 조회는 서로 다른 내장된 처리 의존 관계를 제공하는 방법인ReactQueryFunctionContext을 제공했다.

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
    }
  )
}
이 모든 것은 매우 좋으나, 여전히 약간의 결함이 있다.
  • 패키지의 모든 내용을 사용하여 조회를 구축할 수 있습니다
  • queryKey를 사용하여 상술한 방식으로 URL을 구축하는 것은 여전히 안전하지 않습니다. 모든 내용을 문자열화할 수 있기 때문입니다.
  • 중점 공장을 조회하다.


    이것이 바로 관건적인 공장이 다시 나타난 곳이다.만약 우리가 안전한 검색 키 공장을 가지고 키를 구축한다면, 이 공장의 되돌아오는 형식을 사용하여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 인터페이스가 얇으며/또는 순수한 자바스크립트를 사용한다면, 이 길을 걷고 싶지 않을 수도 있습니다.관례에 따라 너의 구체적인 상황에 가장 의미 있는 도구와 방법을 선택하다🙌
    오늘은 여기까지.언제든지 연락 주세요.
    만약 당신에게 어떤 문제가 있거나, 아래에 평론을 남겨라⬇️

    좋은 웹페이지 즐겨찾기