Is there a method to remove oneself from ThunkAction?

Is there a way to retrieve reference for unsubscribing from a ThunkAction like the following:

export const fetchSomeData = () => async (dispatch: Dispatch, getState: GetState) => {
  let unsubscribeUserAuth: UnsubscribeUserAuth | null = null;
  let unsubscribeDataSnapshot: UnsubscribeDataSnapshot | null = null;

  try {
    // Subscribe to user authentication state changes
    unsubscribeUserAuth = getAuth().onAuthStateChanged(user => {
      // check if user is authenticated
    });

    // Subscribe to data snapshot updates
    unsubscribeDataSnapshot = onSnapshot(queryRef, (docsSnapshot) => {
      // dispatches payload data and sets loaded to true
    })

    return {
      unsubscribe: () => {
        if (unsubscribeUserAuth && unsubscribeDataSnapshot) {
          unsubscribeUserAuth();
          unsubscribeDataSnapshot();
        }
      }
    }

  catch(error) {
    // dispatches error and sets error flag to true
    if (unsubscribeUserAuth && unsubscribeDataSnapshot) {
      unsubscribeUserAuth();
      unsubscribeDataSnapshot();
    }
  }
}

I am attempting to execute this from a React useEffect

const { loaded } = useSelector(state => ({
  loaded: state.fireReducer.loaded,
}))

const { fetchSomeData } = useActions({
  fetchSomeData: fireActions.fetchSomeData,
});

useEffect(() => {
  let actionReference;
  if (!loaded) {
    actionReference = fetchSomeData();
  }

  return () => {
    actionReference.unsubscribe();
  }
}, [loaded])

Answer №1

It appears that the issue lies not in needing to "unsubscribe" the thunk, but rather in requiring the "thing" within the thunk to unsubscribe - specifically, the firebase subscriptions. In my view, employing a custom React hook would be a more suitable approach for this task, as it allows for better integration with the React component lifecycle, similar to how you are utilizing the useEffect hook.

For instance:

import store from '../path/to/store';

const useFirebase = (loaded: boolean) => {
  useEffect(() => {
    let unsubscribeAuth: UnsubscribeAuth | null = null;
    let unsubscribeSnapshot: UnsubscribeSnapshot | null = null;

    if (!loaded) {
      // Subscribe to auth state changes
      unsubscribeAuth = getAuth().onAuthStateChanged(user => {
        // check if authenticated
      });

      // Subscribe to snapshot updates
      unsubscribeSnapshot = onSnapshot(queryRef, (docsSnapshot) => {
        // store.dispatch payload
      });
    }

    return () => {
      if (unsubscribeAuth && unsubscribeSnapshot) {
        unsubscribeAuth();
        unsubscribeSnapshot();
      }
    }
  }, [loaded]);
};

Usage:

useFirebase(loaded);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Display sub-objects within Chart.js

I'm currently tackling a project in Ionic 3 where I am utilizing an API that returns a JSON response with nested objects. My goal is to display certain aspects of these objects within a bar graph using chart.js. Unfortunately, I lack experience in ma ...

Exploring Angular 17 SSR: How to Determine if Component Output Event is Subscribed

Developing a toolbar component with an action button in Angular 17 SSR. The button is a generic one, and I am attempting to determine if the component output events are being observed to determine which buttons are displayed. Is the code below valid? < ...

"Is it possible to add an entire object to formData in one

I am looking to send both an image list and product data to an ASP.net api using formData. I have successfully sent the images, but now I am struggling with appending the entire object. I have come across some methods in JS like JSON.stringfy(object) or Ob ...

Unraveling the intricacies of the relationship between `extends` and function types in TypeScript

Example 1 seems clear to me type A = (1 | 2 | 3) extends (infer I) ? [I] : never; // A = [1 | 2 | 3] In Example 2, the type variables are being intersected but I'm unsure why type A = ( ((_: 1) => void) | ((_: 2) => void) | ((_: 3) => ...

Clicking on an element- how can I find the nearest element?

Encountering an issue with my next js app where I am attempting to assign a class to an element upon clicking a button. The problem arises when trying to access the next div using the following code snippet: console.log(e.target.closest('.request_quot ...

What is the best way to assign a variable with the type (x:number)=>{y:number,z:number}?

I am trying to initialize a variable called foo, but my current code is not compiling successfully. let foo: (x: number) => {y:number,z: number} = (x) => {x+1, x+2}; This results in the following error: Left side of comma operator is unused and ha ...

In Vue3, when using the `script setup` with the `withDefaults` option for a nested object, its attributes are marked as required. How can this issue

I have defined a props object with certain attributes: interface Props { formList: BaseSearchFormListItemType[], inline?: boolean searchBtn?: { show?: boolean text?: string type?: string size?: string } } const props = withDefaults( ...

Transform the function into an observable form

Is there a way to transform this function into an observable? I need it to check for the existence of a document based on a query, and I want to be able to subscribe to it in order to create a new document if one does not already exist. Unfortunately, I a ...

Substitute all attributes of objects with a different designation

I need to update all object properties from label to text. Given: [ { "value": "45a8", "label": "45A8", "children": [ { "value": "45a8.ba08", "label": "BA08", &q ...

An error occurred in TSX + React: Uncaught TypeError - The property 'setState' cannot be read since it is undefined in Menu.handleClick

Currently, I am utilizing [email protected] along with react and react-dom @15.6.2. Encountering a troublesome issue that I can't seem to debug: Uncaught TypeError: Cannot read property 'setState' of undefined at Menu.handleClick. Thi ...

Transferring 'properties' to child components and selectively displaying them based on conditions

This is the code for my loginButton, which acts as a wrapper for the Button component in another file. 'use client'; import { useRouter } from 'next/navigation'; import { useTransition } from 'react'; interface LoginButtonPr ...

Pass the variant value from Shopify/Restyle to the child component in a seamless way

Forgive me if this question has already been addressed elsewhere. Is there a secure method to transmit variant information to child components? I'm attempting to craft a personalized Button component using the useRestyle hook as outlined in the follo ...

Conceal components using routing in Angular2 release candidate 1

I have a request regarding certain elements that are to be displayed on all pages except the login page. I am considering using either ngIf or the hidden property of the elements to hide them when the user is on the login page. Here is what I have attempt ...

Having trouble locating node_modules post deployment?

Although the title may lead you astray, please stay with me for a moment. I've created a basic Angular2 application in Visual Studio 2015 and have now deployed it to Azure. While having node_modules in the development environment worked perfectly fi ...

What is the process for creating an index signature for a type alias representing a Map in Typescript?

Suppose I have a custom type for a Map as follows: type MyCustomMap = Map<string, number>; Is there any way to add an index signature to this type so that I can set key-value pairs after initializing it? I have been able to achieve this with types ...

Issue encountered in Cypress while attempting to locate an identifier beginning with a numeric value

My struggle is with finding an element by id using Cypress. The Cypress selector playground provided the following code: get("#\33 -2") Unfortunately, when I execute this code in Cypress, it results in an error: Syntax error, unrecognized expressio ...

The never-ending cycle of React Redux

Whenever a user updates an input bar, I want to trigger a fetch request to my REST API. However, I am facing an issue where the componentDidUpdate method keeps calling the action creator, which then dispatches the JSON to the reducer, causing the state to ...

Dealing with Errors in Node.js Using Typescript and Express

As I embark on my journey with Node and Typescript, a question has cropped up in my mind. There are two key files in my project: server.ts import express = require('express'); import IConfiguration from "../config/config"; export default clas ...

The detection of my query parameters is not working as expected

Creating an Angular application that dynamically loads a different login page based on the "groupId" set in the URL is my current challenge. The approach involves sending each client a unique URL containing a specific "groupId" parameter. A template is the ...

How to eliminate a particular validator from a form group in Angular

My goal is to eliminate the specific validator from the validator array so that I can reconfigure the controls when certain values have changed. I am aware of the traditional solution where I would need to repeatedly set validators. checked(event: MatC ...