DEV Community

Cover image for Using Middleware with Dojo Processes
Rene Rubalcava
Rene Rubalcava

Posted on • Originally published at learn-dojo.com

Using Middleware with Dojo Processes

We previously looked at how you can manage state in Dojo with processes and stores. This isn't only a flexible way you can manage state in your applications, but it provides some hooks for you to be able to stick your nose into your applications business.

Maybe you want to manage some state in your application when you begin to fetch data and when you have completed fetching data. You could try to manage this in the widget itself or maybe in the process. This is kind of tricky though. Each process can update the store, and you could even run multiple processes at the same time, but it's treated as a single transaction. So you can't really start a process, change the loading state and change it back when you're done in a way that would update your widget in that single transaction.

// src/processes/starwarsProcesses.ts
const fetchItems = commandFactory<Item>(async ({ path }) => {
  // where do we change the starting state?
  const response = await fetch("https://swapi.co/api/");
  const json = await response.json();
  const items: Item[] = Object.keys(json).map(key => {
    return {
      label: key,
      value: json[key]
    };
  });
  // this workflow doesn't work, the widget never gets the 'true' state
  // this is a single transaction
  return [
    replace(path("loading"), true),
    replace(path("items"), items),
    replace(path("loading"), false)
  ];
});
Enter fullscreen mode Exit fullscreen mode

Middleware

But fear not! Dojo has a way for you to run some middleware on your processes to do all sorts of cool things! There is some more detailed information here.

What kind of tasks can you do with middleware?

  • Transform the fetched result of your process.
  • Validate arguments passed to your process.
  • Define a loading state.
  • Add logging and telemetry.
  • Runtime caching.

And I'm sure you can think of many more uses!

The middleware API allows you to provide after and before methods. So in my use case above, We can update the loading state of the process before and after it begins.

To update some loading state, that could look like this!

// src/processes/starWarsProcess.ts
const progress: ProcessCallback = () => ({
  before(payload, { apply, path }) {
    // update the app store before the process is run
    apply([replace(path("loading"), true)], true);
  },
  after(error, { apply, path }) {
    // update the app store when process is finished
    apply([replace(path("loading"), false)], true);
  }
});
Enter fullscreen mode Exit fullscreen mode

In the middleware methods, we're given an apply and a path. The apply lets us apply an operation to the store, and the path lets us pick the property that we want to act on. In this case, we can use the replace operation to update an existing property. This state update will propagate to any other parts of the application that are using this store.

Now we can update the process to use this middleware!

// src/processes/starWarsProcess.ts
export const fetchItemsProcess = createProcess(
  "fetch-items", // process name
  [fetchItems],  // command
  [progress]     // middleware
);
Enter fullscreen mode Exit fullscreen mode

With the middleware in place, we can update the widget so that it can recognize when data is being fetched.

// src/widgets/APIExplorer.tsx
export class APIExplorer extends WidgetBase<ExplorerProperties> {
  ...
  render() {
    return (
      ...
      <TextArea
       rows={25}
       theme={theme}
       value={loading ? "Loading..." : result}
      />
      ...
    );
  }
  ...
}
Enter fullscreen mode Exit fullscreen mode

Now in the widget, if the store loading state is true, we can show some loading text, if it's not loading, we can show the result!

You can see what this looks like here!

Summary

The ability to have the after/before middleware in our application state is not only practical, but incredibly flexible. We've just scratched the surface of what you can do with Dojo middleware, but I'm excited about the possibilities and I'm sure you are too!

Top comments (0)