DEV Community

Benny Powers ๐Ÿ‡ฎ๐Ÿ‡ฑ๐Ÿ‡จ๐Ÿ‡ฆ
Benny Powers ๐Ÿ‡ฎ๐Ÿ‡ฑ๐Ÿ‡จ๐Ÿ‡ฆ

Posted on • Edited on • Originally published at bennypowers.dev

Let's Write a Redux Controller for Web Components

Elliott Marquez challenged me to write a redux controller on the Lit & Friends slack.

So let's get cracking!

Step 0: The Setup

First step let's make a new project and import some dependencies to help us develop.

mkdir controllers cd controllers git init npm init --yes npm i -D typescript lit touch reducer.ts 
Enter fullscreen mode Exit fullscreen mode

Ok next we'll set up the controller class in reducer.ts

import type { ReactiveController, ReactiveControllerHost } from 'lit'; export class ReducerController implements ReactiveController { constructor( public host: ReactiveControllerHost, ) { host.addController(this); } hostUpdate()?: void; } 
Enter fullscreen mode Exit fullscreen mode

That hostUpdate signature is just to keep typescript from complaining. ๐Ÿคท.

Step 1: Reducers

Our controller essentially bolts some statefullness onto a function which takes some state T and some action A and returns some other or the same state T. So let's formalize that:

type Reducer<T, A> = (state: T, action: A) => T; 
Enter fullscreen mode Exit fullscreen mode

The controller should take that reducer, along with some initial state, and pin them to the class instance.

export class ReducerController<T = unknown, A = unknown> implements ReactiveController { public state: T; constructor( private host: ReactiveControllerHost, public reducer: Reducer<T, A>, public initialState: T, ) { this.host.addController(this); this.state = initialState; } hostUpdate?():void } 
Enter fullscreen mode Exit fullscreen mode

Step 2: Actions

Believe it or not we're pretty much done. The last piece we need is to implement a dispatch method which takes an action A and updates the host.

dispatch(action: A): void { this.state = this.reducer(this.state, action); this.host.requestUpdate(); } 
Enter fullscreen mode Exit fullscreen mode

And, as Chef John would say, that's it!

If we want to use our controller, we just create it on a compatible host (like LitElement) and we're off to the races:

Live Demo

Top comments (0)