es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Puede un gancho useQuery saltarse a sí mismo?

En lugar de omitir una consulta pasando “skipToken” a su gancho “useQuery”, ¿es posible que la consulta se omita a sí misma?

En la sección de Referencia de la API de RTK Query Estableciendo encabezados predeterminados en las solicitudes, hay un ejemplo en el que “prepareHeaders” verifica la tienda en busca de un token de autenticación, y si está presente, lo establece como encabezado de autorización para la solicitud. Esto es exactamente lo que estoy haciendo en mi aplicación.

Pero si el token NO está en la tienda, la solicitud fallaría con un código HTTP 403. Aún peor, ese fallo es almacenado en caché por RTKQ, por lo que el gancho “useQuery” volverá a fallar la próxima vez, incluso si el token de autenticación se ha vuelto disponible en el ínterin.

Entonces, en ese caso, quiero que la consulta se omita. Solo veo 2 formas de hacer esto, y ninguna es satisfactoria:

  • Una forma sería que el componente React verifique la tienda y pase “skipToken” si el token de autenticación no está en la tienda. Pero esto es molesto porque tengo que recordar hacer esta misma verificación en cada componente que utiliza la consulta. Y creo que el mecanismo de autenticación debería ser interno al código de la consulta.

  • Otra posibilidad es anular “queryFn”, hacer la verificación allí y devolver un error si el token de autenticación no está presente. Esto es un poco engorroso y todavía deja el mismo problema que antes: el fallo se almacena en caché, por lo que el gancho “useQuery” seguirá devolviendo un error incluso cuando el token de autenticación esté disponible.

Me gustaría una forma de que la consulta pueda omitirse si el token de autenticación no está presente (como si se hubiera pasado “skipToken” al gancho “useQuery”). ¿Es posible hacer algo así?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Sí, es posible que la consulta se salte a sí misma si se cumple una cierta condición, sin depender de pasar skipToken desde el componente React o anular queryFn. Esto se puede lograr utilizando skipToken como clave de caché y devolviendo condicionalmente un objeto de resultado especial que le dice a RTKQ que omita la consulta y utilice en su lugar el resultado en caché. Aquí tienes un ejemplo de implementación:

    import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query';
    
    const api = createApi({
      baseQuery: fetchBaseQuery({
        baseUrl: 'https://api.example.com',
        prepareHeaders: (headers, { getState }) => {
          const token = selectAuthToken(getState()); // selectAuthToken se define en otro lugar
          if (token) {
            headers.set('Authorization', `Bearer ${token}`);
          }
          return headers;
        },
      }),
      endpoints: (builder) => ({
        someEndpoint: builder.query({
          query: () => ({ url: '/some-endpoint' }),
          transformResponse: (response) => response.data,
        }),
      }),
    });
    
    api.injectEndpoints({
      endpoints: (builder) => ({
        // Agrega un punto final proxy que utiliza skipToken como clave de caché
        skipIfNoAuthToken: builder.query({
          query: (skipToken) => ({ url: '/skip-if-no-auth-token', skipToken }),
          // Devuelve un objeto de resultado especial si el token no está presente
          // Esto hará que RTKQ omita la consulta y utilice el resultado en caché en su lugar
          async onQueryStarted({ skipToken }, { dispatch, cache }) {
            const token = selectAuthToken(selectAppStore()); // selectAppStore se define en otro lugar
            if (!token) {
              dispatch({
                type: 'QUERY_SKIPPED',
                requestId: 'skipIfNoAuthToken',
                meta: { skip: true, cacheKey: cache.serializeQueryArgs(['skipIfNoAuthToken', skipToken]) },
                payload: undefined,
              });
            }
          },
        }),
      }),
    });
    
    // Uso en un componente React:
    const Component = () => {
      const { isFetching, isSuccess, data } = useSkipIfNoAuthTokenQuery('mi-skip-token');
    
      // ...
    };
    

    Con esta implementación en su lugar, cuando se llama a la consulta skipIfNoAuthToken con un valor de skipToken, primero se ejecutará su hook onQueryStarted. En este hook, se verifica el token de autenticación y, si no está presente, la consulta se omite devolviendo un objeto de resultado especial con { meta: { skip: true, cacheKey: ... }, payload: undefined }. El cacheKey se construye utilizando cache.serializeQueryArgs para incluir el nombre de la consulta (skipIfNoAuthToken) y el argumento skipToken.

    Cuando RTKQ ve este objeto de resultado especial, omite la consulta y devuelve el resultado en caché si está disponible. Esto significa que cualquier llamada posterior a useSkipIfNoAuthTokenQuery('mi-skip-token') devolverá el mismo objeto de resultado, hasta que el token de autenticación esté disponible y provoque una invalidación de caché (por ejemplo, llamando a la API global invalidateQueries).

Comments are closed.