This article is about fixing wait for dispatch to complete in jeffbski redux-logic
  • 25-Jan-2023
Lightrun Team
Author Lightrun Team
Share
This article is about fixing wait for dispatch to complete in jeffbski redux-logic

Wait for dispatch to complete in jeffbski redux-logic

Lightrun Team
Lightrun Team
25-Jan-2023

Explanation of the problem

The problem that is being described is related to managing the flow of logic in an application that uses the createLogic function from the redux-logic library. The code provided shows two logic functions, updateSomething and doSomething, which are used to handle specific actions dispatched to the application’s store.

The first issue being described is related to the handling of the result of an action. The updateSomething logic function is performing an asynchronous POST request to a specified url and then calls the done(data) function, passing the data received as a parameter. However, the problem is that there is no clear way of accessing this data in the next logic function, doSomething.

The second issue is related to the flow of actions being dispatched within the doSomething logic function. The code dispatches the updateSomething action and then immediately dispatches another action doAnotherThingUponCompleteOnlyInThisFlow(). However, the problem is that this second action is being dispatched before the updateSomething action has completed, which is causing the wrong flow in the application. The code does not wait for the updateSomething action to complete before dispatching the next action.

Troubleshooting with the Lightrun Developer Observability Platform

Getting a sense of what’s actually happening inside a live application is a frustrating experience, one that relies mostly on querying and observing whatever logs were written during development.
Lightrun is a Developer Observability Platform, allowing developers to add telemetry to live applications in real-time, on-demand, and right from the IDE.

  • Instantly add logs to, set metrics in, and take snapshots of live applications
  • Insights delivered straight to your IDE or CLI
  • Works where you do: dev, QA, staging, CI/CD, and production

Start for free today

Problem solution for wait for dispatch to complete in jeffbski redux-logic

One solution for waiting for a dispatch to complete before continuing with other actions is to have the API calls that manipulate data return a promise or observable. This allows the developer to know when the API calls have completed and proceed with dispatching actions synchronously. For example, in the following code snippet, the developer is using the async/await pattern to wait for the API call to complete before dispatching the “widgetsSuccess” action:

export const doSomething = createLogic({
    type: actions.doSomething,

    async process({ getState, action, api }, dispatch, done) {
        const {data} = await api.getWidgets();
        dispatch(widgetsSuccess(data));
        //...
    }
});

Additionally, the developer can use a middleware like the one described in the second answer, which waits for specific action types to resolve before continuing with the next action. This allows for more fine-grained control over the flow of actions and can be useful in cases where there are multiple async actions that need to be coordinated.

const typeResolvers = {};
let currentStore;

export const dispatchProcessMiddleware = (store) => {
    currentStore = store;
    return next => (action) => {
        const resolvers = typeResolvers[action.type];
        if (resolvers && resolvers.length > 0) {
            resolvers.forEach(resolve => resolve());
        }

Other popular problems with jeffbski redux-logic

Problem: Handling Asynchronous Actions

One of the most common problems with jeffbski redux-logic is handling asynchronous actions. When dispatching an action that involves making an API call or performing some other asynchronous operation, it can be difficult to know when the action has completed. This can lead to issues when trying to dispatch another action that relies on the completion of the previous action.

Solution:

One way to solve this issue is to have the API calls that manipulate data return a promise or observable. This way, the developer can know when the API calls have completed. The logic can then dispatch actions synchronously, knowing when the previous action has completed.

Another way of solving this problem is by using middleware like the one described in the answer 2, that allows you to wait for a specific action to be completed before dispatching other actions.

Problem: Handling Errors

Another common problem with jeffbski redux-logic is handling errors that occur during the processing of an action. When an error occurs, it can be difficult to know how to handle it and ensure that the application remains in a consistent state.

Solution:

One way to solve this issue is to have a centralized error handling mechanism in place. This can be achieved by using middleware that intercepts all actions and checks for errors. The middleware can then handle the error and dispatch an action to update the state of the application accordingly.

Another way to handle errors is by using try-catch blocks in the process function of the logic. This way, when an error occurs it can be caught and handled within the logic.

Problem: Testing

Testing is always a challenge when working with redux-logic. Because the logic is tightly coupled to the store and the actions, it can be difficult to write tests that are isolated from the rest of the application.

Solution:

One way to solve this problem is by using a library like redux-logic-test that provides a set of helper functions that make it easy to test the logic. This library allows you to easily create a mock store and dispatch actions, making it easy to test the logic in isolation.

Another way to solve this problem is by using a mocking library to mock the store and actions and testing the logic in isolation.

It’s also important to keep in mind that keeping the logic simple and small, using a functional programming approach, can make the testing process easier.

A brief introduction to jeffbski redux-logic

jeffbski redux-logic is a middleware library that allows developers to handle side-effects and business logic in a Redux application. It provides a powerful way to separate the logic of an application from the state management, allowing developers to write cleaner and more maintainable code. The library is based on the concept of “logic”, which is a function that receives an action and can perform various operations, such as dispatching new actions, making API calls, or updating the state of the application.

One of the main benefits of using jeffbski redux-logic is that it allows developers to easily test the logic of their application without having to mock the entire Redux store or create complex test fixtures. The logic functions can be tested in isolation, which makes it easier to identify and fix bugs. Additionally, the library provides a powerful way to organize and reuse logic across different parts of the application, making it easy to implement cross-cutting concerns such as error handling, security, and analytics. Overall, jeffbski redux-logic is a powerful tool for managing complex logic in a Redux application, making it easier to write maintainable and testable code.

Most popular use cases for jeffbski redux-logic

  1. Jeffbski redux-logic can be used to handle complex logic and side-effects in a Redux application, such as making API calls, working with async data, and dispatching multiple actions. This can help keep the Redux reducers and actions simple and focused on handling the state of the application.
import { createLogic } from 'redux-logic';

const fetchUsersLogic = createLogic({
  type: FETCH_USERS,
  async process({ action, httpClient }) {
    try {
      const response = await httpClient.get('/users');
      this.dispatch(fetchUsersSuccess(response.data));
    } catch (error) {
      this.dispatch(fetchUsersFailure(error));
    }
  }
});
  1. Jeffbski redux-logic can also be used to handle cross-cutting concerns, such as validation, authentication, and logging, in a centralized and reusable way.
const validateUserLogic = createLogic({
  type: ADD_USER,
  validate({ action }, allow, reject) {
    const { user } = action.payload;
    if (!user.name) {
      return reject(addUserFailure('Name is required'));
    }
    if (!user.email) {
      return reject(addUserFailure('Email is required'));
    }
    allow(action);
  }
});
  1. Jeffbski redux-logic also allows for powerful flow control capabilities such as canceling, chaining and parallel processing of logic.
const fetchUsersLogic = createLogic({
  type: FETCH_USERS,
  latest: true, // take latest only
  async process({ action, httpClient }, dispatch, done) {
    try {
      const response = await httpClient.get('/users');
      dispatch(fetchUsersSuccess(response.data));
    } catch (error) {
      dispatch(fetchUsersFailure(error));
    }
    done();
  }
});
Share

It’s Really not that Complicated.

You can actually understand what’s going on inside your live applications.

Try Lightrun’s Playground

Lets Talk!

Looking for more information about Lightrun and debugging?
We’d love to hear from you!
Drop us a line and we’ll get back to you shortly.

By submitting this form, I agree to Lightrun’s Privacy Policy and Terms of Use.