Tengo una serie de componentes que usan datos derivados de una respuesta de consulta RTK. Si bien se deriva de la misma respuesta con los mismos argumentos de consulta, cada componente necesita que los datos pasen a través de un conjunto de filtros del lado del cliente relativamente costosos (cuyos argumentos son propiedades de segmento de la tienda redux) que pueden no ser los mismos para cada componente. Sin embargo, todos los componentes requieren que los datos pasen por al menos dos filtros específicos. Esta relación se muestra en el siguiente diagrama:
¿Es posible suscribirse a los datos después de que hayan sido transformados por un filtro/conjunto de filtros específico?
Enfoques que he considerado:
extraReducers y escuche la finalización de la consulta, luego realice la operación de filtro. Esto funciona bien ya que puedo usar los argumentos de filtro en el reductor, pero creo que no hay forma de que repita la operación con nuevos argumentos una vez que los argumentos de filtro se han actualizado pero los datos de consulta se han mantenido igual.Intuitivamente, pensaría que sería ideal una devolución de llamada que funcione como un software intermedio entre el resultado de la API y los datos suscritos del componente. Soy consciente de la opción transformResponse definible en el segmento API, pero creo que no es apropiado ni posible para esta situación.
const queryResult = endpointName.useQuery(args, filterArgs, (data, filterArgs) => { return data.performSomeSharedFilterOperationHere(filterArgs); } );Idealmente, los datos se actualizarían cuando cambien los argumentos de consulta O cuando cambien los argumentos de filtro. Supongo que la diferencia entre esto y una implementación simple de useEffect es que en el escenario useEffect, los datos no se 'comparten' y las operaciones de filtro ocurren nSubscribedComponents veces.
¿Hay algo en RTK que permita el comportamiento que busco?
Creo que la respuesta correcta aquí es usar la opción selectFromResult en los ganchos de consulta .
Cree los siguientes selectores de reselección:
const selectFilter1 = createSelector( // Start by taking the actual response data as its input (inputData) => inputData, (data) => // magically transform here ) const selectFilter2 = createSelector( selectFilter1, (filteredData) => // magically transform here ) // repeat for filters 2 and 3Luego, en el componente:
const { filteredData} = useGetPostsQuery(undefined, { selectFromResult: result => ({ // We can optionally include the other metadata fields from the result here ...result, // Include a field called `filteredData` in the result object, // and memoize the calculation filteredData: selectFilter3(result.data) }) }) Los componentes compartirán la misma instancia del selector, por lo que cada vez que se llame al selector, se debe pasar la misma result.data de datos de resultados y, por lo tanto, los cálculos deben memorizarse. Los primeros dos selectores deben memorizar sus resultados y, por lo tanto, selectFilter3 solo tendrá que volver a calcular cuando cambie el resultado de selectFilter2 , etc.