Here's a minimalist no-frills Redux Toolkit & LitElement example
Published: 2021-02-21 10:11:29

Picture by [@16pxl](https://twitter.com/16pxl/status/1059615735964688385)

Tired of full boilerplate Redux examples? What about all the Redux Toolkit examples that try to explain how much complexity is now reduced into opinionated functions... based on your *knowledge* of Redux?

I believe it's the most minimalist examples based on the simplest systems which tell you all.

> *The way to build a complex system that works is to build it from very simple systems that work.*
> — Kevin Kelly

Here I present you a simple system of a Redux Toolkit store and two LitElement based Web Components.

# The Components

Our system is based on 2 components: one to control a variable and another one to show the state of the variable. As simple as it can get.

Of course you won't use Redux Toolkit to do that if you have just 2 components, but that's not why you're here, isn't it?

I've called them `auth-control` and `auth-info`, it's a dumb system to sign in and sign out just by clicking on buttons that say "Sign in" and "Sign out". See? No frills as promised 😂

## `<auth-info>`

This component just shows a salute if you're signed in, based on an `isAuthenticated` property.

```js
import { LitElement, html } from 'lit-element'

class AuthInfo extends LitElement {

  static get properties() {
    return {
      isAuthenticated: Boolean,
    }
  }

  render() {
    if (this.isAuthenticated) {
      return html`
        <p>Hi, you're signed in</p>
      `
    }
  }
}

window.customElements.define('auth-info', AuthInfo);
```

## `<auth-control>`

Here's the controlling component. As you can see, they have a property with the same name: `isAuthenticated`.

```js
import { LitElement, html } from 'lit-element'

class AuthControl extends LitElement {

  static get properties() {
    return {
      isAuthenticated: Boolean
    };
  }
  
  handleSignIn () {
    this.isAuthenticated = true
  }
  
  handleSignOut () {
    this.isAuthenticated = false
  }

  render() {
    if (this.isAuthenticated) {
      return html`
        <button @click=${this.handleSignOut}>Sign Out</button>
      `
    }
    return html`
      <button @click=${this.handleSignIn}>Sign In</button>
    `
  }
}

window.customElements.define('auth-control', AuthControl)
```

#The Store

The goal is to share the state of the property `isAuthenticated` from a global state store. We will use Redux Toolkit to accomplish that:

```js
import { createSlice, configureStore } from '@reduxjs/toolkit'

const { actions: authActions, reducer: authReducer } = createSlice({
  name: 'isAuthenticated',
  initialState: false,
  reducers: {
    signIn: () => true,
    signOut: () => false
  }
})

const { signIn, signOut } = authActions

const store = configureStore({
  reducer: {
    isAuthenticated: authReducer
  }
})

export { store, signIn, signOut }
```

Note the neat use of destructuring to obtain all the necessary information from `createSlice`. If you want to add more data to the store: just create a new slice, add the obtained reducer to the list of reducers to feed to `configureStore` and export the actions so that your app can update the state.

# The connection

Now we need to connect the store with both components. In order to do that we'll use a [`connect` mixin from Polymer project pwa-helpers](https://github.com/Polymer/pwa-helpers#connect-mixinjs).

This mixin will add logic to our component that will end up calling `stateChanged` every time the state changes, so to complete the connection we have to implement this callback function as well.

## Connecting `<auth-info>`

```js
...
import { connect } from 'pwa-helpers'
import { store } from './state.js'

class AuthInfo extends connect(store)(LitElement) {
...
  stateChanged(state) {
    this.isAuthenticated = state.isAuthenticated;
  }
...
```
That's it. You don't even need a constructor, as the store dispatches the initial state on connection.

## Connecting `<auth-control>`

```js
...
import { connect } from 'pwa-helpers'
import { store, signIn, signOut } from './state.js'

class AuthControl extends connect(store)(LitElement) {
...
  stateChanged(state) {
    this.isAuthenticated = state.isAuthenticated;
  }

  handleSignIn () {
    store.dispatch(signIn())
  }
  
  handleSignOut () {
    store.dispatch(signOut())
  }
...
```
Same here, plus we imported the actions to dispatch when handling the events for the sign in and sign out buttons.

## Final touches

An HTML page to hold the components together and a build process to resolve the dependencies for LitElement and others is all you might need. We're using Snowpack for that.

###Buildless anyone?

You could perfectly use packages from a CDN like [Skypack](https://www.skypack.dev/) or [UNPKG](https://unpkg.com/) and skip the build process altogether if you fancy. Like so:

```js
-- import { LitElement, html } from 'lit-element'
++ import { LitElement, html } from 'https://cdn.skypack.dev/lit-element'
```
Having a well thought buildless process have great benefits. In fact, Snowpack has an option to do just something like we just did there, using CDN packages instead of installing them manually. It's called [Streaming Imports](https://www.snowpack.dev/guides/streaming-imports) in case you're interested 😉.

#Complete example
Please dig in the whole example I've done for you in Glitch. Feel free to remix it there and leave feedback in the comments 👇 Any question or comment will be welcome!

{% glitch lit-element-redux-toolkit-minimalist-example %}