最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Can i subscribe to filtered RTK query data results across multiple components? - Stack Overflow

programmeradmin7浏览0评论

I have a series of ponents which all use data derived from an RTK Query response. While derived from the same response with the same query arguments, each ponent needs the data to pass through a set of relatively expensive client-side filters (whose args are redux store slice properties) which may not be the same for each ponent. However, all of the ponents require the data to pass through at least two specific filters. This relationship is shown by the following diagram:

Is it possible to subscribe to the data after it has been transformed by a specific filter/ set of filters?

Approaches I have considered:

  • Use query in all ponents, apply whichever filters are required in some useEffect or useMemo. This is not preferable since that means at least 2 filters are being duplicated nComponents times.
  • Use createSlice extraReducers option and listen for query pletion, then perform filter operation. This works fine since i can use the filter args in the reducer, but I believe there is no way for me to repeat the operation with new args once the filter args have been updated but the query data has stayed the same.
  • Subscribe one ponent, publish data to slice after each corresponding filter stage, subscribe each ponent to corresponding data. This is how i currently have this implemented, but it is not ideal because it couples ponents together which i wish to avoid, bloats one ponent which is sort of arbitrarily chosen, and produces frequent large state actions which slow down my application.
  • Raise query subscription to shared ancestor ponent, then pass data as props. This is not ideal because these ponents are at varying depths relative to their shared ancestor, which I imagine would result in prop drilling for at least some ponent.
  • Use react context to share results of first 2 filter operations with corresponding ponents. Haven't looked into this much yet; would it work with a query subscription?

Intuitively i would think some callback that operates as some middleware between the API result and the ponent's subscribed data would be ideal. I am aware of the transformResponse option definable in the API slice, but I believe it is not appropriate or possible for this situation.

const queryResult = endpointName.useQuery(args, filterArgs, (data, filterArgs) => {
    return data.performSomeSharedFilterOperationHere(filterArgs);
    } 
);

Ideally the data would update when query args change OR when filter args change. I suppose the difference between this and a simple useEffect implementation is that in the useEffect scenario, the data is not 'shared' and the filter operations occur nSubscribedComponents times.

Is there anything in RTK that permits the behavior I am seeking?

I have a series of ponents which all use data derived from an RTK Query response. While derived from the same response with the same query arguments, each ponent needs the data to pass through a set of relatively expensive client-side filters (whose args are redux store slice properties) which may not be the same for each ponent. However, all of the ponents require the data to pass through at least two specific filters. This relationship is shown by the following diagram:

Is it possible to subscribe to the data after it has been transformed by a specific filter/ set of filters?

Approaches I have considered:

  • Use query in all ponents, apply whichever filters are required in some useEffect or useMemo. This is not preferable since that means at least 2 filters are being duplicated nComponents times.
  • Use createSlice extraReducers option and listen for query pletion, then perform filter operation. This works fine since i can use the filter args in the reducer, but I believe there is no way for me to repeat the operation with new args once the filter args have been updated but the query data has stayed the same.
  • Subscribe one ponent, publish data to slice after each corresponding filter stage, subscribe each ponent to corresponding data. This is how i currently have this implemented, but it is not ideal because it couples ponents together which i wish to avoid, bloats one ponent which is sort of arbitrarily chosen, and produces frequent large state actions which slow down my application.
  • Raise query subscription to shared ancestor ponent, then pass data as props. This is not ideal because these ponents are at varying depths relative to their shared ancestor, which I imagine would result in prop drilling for at least some ponent.
  • Use react context to share results of first 2 filter operations with corresponding ponents. Haven't looked into this much yet; would it work with a query subscription?

Intuitively i would think some callback that operates as some middleware between the API result and the ponent's subscribed data would be ideal. I am aware of the transformResponse option definable in the API slice, but I believe it is not appropriate or possible for this situation.

const queryResult = endpointName.useQuery(args, filterArgs, (data, filterArgs) => {
    return data.performSomeSharedFilterOperationHere(filterArgs);
    } 
);

Ideally the data would update when query args change OR when filter args change. I suppose the difference between this and a simple useEffect implementation is that in the useEffect scenario, the data is not 'shared' and the filter operations occur nSubscribedComponents times.

Is there anything in RTK that permits the behavior I am seeking?

Share Improve this question edited Feb 11, 2022 at 18:34 paullc asked Feb 11, 2022 at 18:28 paullcpaullc 1752 silver badges12 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 6

I think the right answer here is to use the selectFromResult option in the query hooks.

Create the following Reselect selectors:


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 3

Then, in the ponent:

  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)
    })
  })

The ponents will be sharing the same selector instance, so each time the selector is called the same result.data reference should be passed in, and thus the calculations should memoize. The first couple selectors should memoize their results, and thus selectFilter3 will only have to recalculate when selectFilter2's result changes, etc.

发布评论

评论列表(0)

  1. 暂无评论