BLOC

Business Logic Component

What is bloc?

  • BLoC, or Business Logic Component, is a design pattern in Flutter that manages state and events in an app. It separates the business logic from the user interface
  • Flutter bloc for beginners

solid

import { Bloc, setState } from "@hunk/bloc/solid";
import { createStore } from "solid-js/store";

type CounterEvent = "dec" | "inc";
type CounterState = {
  n: number;
};
type CounterBloc = Bloc<CounterEvent, CounterState>;

export const [counter, setCounter] = createStore<CounterBloc>({
  status: "inc",
  n: 0,
});

export const emitCounter = setState(setCounter, (status, curr, emit) => {
  switch (status) {
    case "inc":
      emit("n", (prev) => prev + (curr.n ?? 0));
      break;
    case "dec":
      emit("n", (prev) => prev - (curr.n ?? 0));
      break;
  }
});

//jsx
function App() {
  return (
    <>
      {counter.n}
      <button onclick={() => emitCounter("inc", { n: 1 })}></button>
      <button onclick={() => emitCounter("dec", { n: 1 })}></button>
    </>
  );
}

qwik

import type { Bloc, setState } from "@hunk/bloc/qwik";

type CounterEvent = "dec" | "inc";
type CounterState = {
  n: number;
};
export type CounterBloc = Bloc<CounterEvent, CounterState>;

export const App = component$(() => {
  const counter = useStore<CounterBloc>({
    state: {
      status: "dec",
      n: 0,
    },
    emit: $(function (this, curr) {
      setState(this.state, curr, (e) => {
        switch (e.type) {
          case "dec":
            this.state.n = this.state.n - (curr.n ?? 0);
            break;
          case "inc":
            this.state.n = this.state.n + (curr.n ?? 0);
            break;
        }
      });
    }),
  });
  return (
    <>
      {counter.state.n}
      <button onClick$={() => counter.emit({ type: "inc", n: 1 })}>
        inc
      </button>
      <button onClick$={() => counter.emit({ type: "dec", n: 1 })}>
        dec
      </button>
    </>
  );
});

svelte

import { _, type Bloc, type V } from "@hunk/bloc/svelte";

type CounterEvent = "dec" | "inc";
type CounterState = {
  n: number;
};
type CounterBloc = Bloc<CounterEvent, CounterState>;

export class Counter implements CounterBloc {
  status: CounterEvent = $state("dec");
  value: V<CounterState> = $state({
    n: 0,
  });
  set(e: CounterEvent, state: Partial<V<CounterState>>) {
    _(e)(this, (ev) => {
      switch (ev) {
        case "dec":
          this.value.n = this.value.n + (state.n ?? 0);
          break;
        case "inc":
          this.value.n = this.value.n - (state.n ?? 0);
          break;
      }
    });
  }
}

<script lang="ts">
  import { Counter } from './counter.svelte';
  const counter = new Counter()
</script>

{counter.value.n}
<button onclick={() => counter.set('dec', {n: 1})}>dec</button>
<button onclick={() => counter.set('inc', {n: 1})}>inc</button>