Search code examples
reactjsreduxreact-hooksreact-reduxrtk-query

Redux-Toolkit-Query: polling, selectfromReult with selectors


I am using below Redux-Toolkit Query (RTKQ) hooks to get information from one of the API and polling this for every 5 seconds, and selectFromResult to get the desired data.

const selectorData = useMemo(() => {
  const emptyValue = {},
        nullValue = null;

  return createSelector(
    [
      (data) => data,
      (data, error) => (error ? error.status : -1),
    ],
    (data, status) => {
      if (status >= 400) return emptyValue;
        
      return data ?? nullValue;
    },
  );
}, []);

const { interestedData } = useMyApiQuery(
  args1,
  {
    selectFromResult: ({ data, error }) => {
      interestedData: selectorData(data, error)
    }), 
    pollingInterval: 5000
  }
);
    
// using interestedData to load the data in UI.

Using selectors, so that the component does not re-render every 5s and gets re-rendered when there is any update in the data or error.

Is this the correct way of using the selector?


Solution

  • Is this the correct way of using the selector?

    I don't believe it is correct. Selector functions are (generally) passed the entire state object and select out their specific slices of state and return a computed value.

    Here you are simply trying to select from the returned query result, not the entire Redux state. I think it is sufficient to simply use a function to do this work.

    Note that a shallow equality check is performed on the overall return value of selectFromResult to determine whether to force a rerender. i.e. it will trigger a rerender if any of the returned object values change reference.

    So long as your emptyValue and nullValue references are stable, the selectFromResult function should work similar to useSelector selector functions right out-of-the-box.

    Outside the component:

    const emptyValue = {};
    const nullValue = null;
    

    Inside the component:

    const { interestedData } = useMyApiQuery(
      args1,
      {
        selectFromResult: ({ data, error }) => {
          interestedData: error?.status >== 400
            ? emptyValue
            : data ?? nullValue
        }), 
        pollingInterval: 5000
      }
    );