Home  >  Q&A  >  body text

How to invalidate all Redux RTK queries when sending special events (socket IO messages)?

I want to synchronize a SPA React application for all users (multiple tabs, multiple users). I wrote a simple reactive hook that listens for specific socket IO messages and updates a state variable based on the message called useGetAllEmployeesQuery:

import { useEffect, useState } from 'react'

export function useRefetchOnMessage (messageType) {
  const [needRefetch, setNeedRefetch] = useState()

  if (!window.io.socket) {
    return
  }

  function handleMessage (e) {
    setNeedRefetch(Date.now())
  }

  useEffect(() => {
    window.io.socket.on(messageType, handleMessage)

    return () => {
      window.io.socket.off(messageType, handleMessage)
    }
  }, [])

  return needRefetch
}

When this event is dispatched, I simply call the RTK refetch() method.

const employees = useGetAllEmployeesQuery(officeId)

const needRefreshEmployees = useRefetchOnMessage('employees changed')

useEffect(() => {
  if (!needRefreshEmployees) return

  employees.refetch()
}, [needRefreshEmployees])

So we need to call it everywhere in the application, let's say we have 5 components that use employee query, we need to call refetch in all components. Many queries only need to be run once to run. (Invalid once)

Is it possible to subscribe to any type of such events in a Redux RTK query configuration?

P粉555682718P粉555682718286 days ago419

reply all(1)I'll reply

  • P粉761718546

    P粉7617185462024-01-30 00:12:10

    You can trigger a subscribed query by invalidating the tag to re query it.

    See invalidateTags: a Redux action creator that can be used to manually invalidate 's cache tags and automatically re-fetch .

    Assuming that the getAllEmployees endpoint provides a tag, such as "employees", you can schedule an action to invalidate the tag and trigger the useGetAllEmployeesQuery hook to re retrieve data.

    const api = createApi({
      ...
      endpoints: builder => ({
        ...
        getAllEmployees: builder.query({
          query: ......,
          ...
          providesTags: ["employees"],
        }),
        ...
      }),
    });
    
    import { useEffect } from 'react';
    import { useDispatch } from 'react-redux';
    import api from '../path/to/apiSlice';
    
    export function useRefetchOnMessage (messageType = "", tags = []) {
      const dispatch = useDispatch();
    
      useEffect(() => {
        const handleMessage = () => {
          dispatch(api.util.invalidateTags(tags));
        };
    
        window.io?.socket?.on(messageType, handleMessage);
    
        return () => {
          window.io?.socket?.off(messageType, handleMessage);
        }
      }, [messageType, tags]);
    }
    

    The UI code simply calls the hook, passing the "employees" token to the useRefetchOnMessage hook.

    const employees = useGetAllEmployeesQuery(officeId);
    useRefetchOnMessage('employees changed', ["employees"]);
    

    reply
    0
  • Cancelreply