Using Flutter’s BLoC pattern in React

Arkadiusz
3 min readApr 4, 2021

--

What is BLoC?

BLoC (Business Logic Component) is the most popular architecture/pattern for Flutter development introduced at Google I/O in 2019.

The main 2 purposes of blocs are moving out business logic out of React components/hooks and managing the state.

What’s wrong with Redux?

Redux requires lots of code to make it work. The problem becomes more noticeable when you try to use it with TypeScript.

Overview

Overview of BLoC in React

Example — Binary Counter

(Example in the links below was created to demonstrate usage of blocs in React, not to solve a problem.)

Click link below to open the demo

NPM Packages

Creating first BLoC

The simplest way to create a BLoC is to use package @bloc-arch/cli. To use this package add the following script to package.json in the scripts section.

"bloc": "bloc —-path=./src/blocs/ -—typescript"

Then, create a directory for blocs. (Path to that directory should be provided to the bloc CLI.)

Now you can generate boilerplate code for your BLoC by running the following script.

npm run bloc -- "bloc name"

The script will create a directory bloc-name with 4 files:

+ src
+ blocs
+ bloc-name
- index.ts
- BlocNameBloc.ts
- BlocNameState.ts
- BlocNameEvent.ts
- package.json

The next step is to specify events and states. In the provided example I created LedBloc that have:

  • events: Toggle, TurnOff
...export class Toggle extends LedEvent {}
export class TurnOff extends LedEvent {}
  • states: Off, On
...export class Off extends LedState {}
export class On extends LedState {}

Now it’s time to write some actual logic. This is done by mapping events to states in the bloc file.

...async *mapEventToState(event: LedEvents.LedEvent) {
if (event instanceof LedEvents.Toggle) {
if (this.getState() instanceof LedStates.Off) {
yield new LedStates.On()
} else {
yield new LedStates.Off()
await new Promise((resolve) => setTimeout(resolve, 100))
this.nextLedBloc?.dispatch(new LedEvents.Toggle())
}
} else if (event instanceof LedEvents.TurnOff) {
yield new LedStates.Off()
}
}
...

If you haven’t used a generator before you could be confused. Think of a generator as a function that doesn’t stop running after returning (yielding) a value.

Connecting BLoC to React

To connect BLoCs to React, use a function setupBlocs from the package @bloc-arch/react.

In the provided example this function is used in the file setupBlocs.ts.

+ src
+ blocs
+ bloc-name
- index.ts
- BlocNameBloc.ts
- BlocNameState.ts
- BlocNameEvent.ts
- setupBlocs.ts <==============
- package.json

This function creates BlocProvider and hooks: useBloc and useWeakBloc from an object containing bloc factories.

...export const { BlocProvider, useBloc, useWeakBloc } = setupBlocs({
foobar: () => new BlocNameBloc()
})

These hooks know what blocs are available so there’s no need to provide template parameters later on.

The make hooks work, add BlocProvider somewhere high in the component’s hierarchy.

ReactDOM.render(
<React.StrictMode>
<BlocProvider>
<Home />
</BlocProvider>
</React.StrictMode>,
document.getElementById('root')
)

Using hooks useBloc and useWeakBloc

To access BLoC from React component use previously generated hooks useBloc or useWeakBloc.

The difference between them is that the useBloc hook will instantiate a new bloc if it doesn’t exist, and remove it on component unmount. You should use useBloc only once for a specified bloc.

When you use hook useBloc you need to pass parameters specified in setupBloc.ts.

// setupBlocs.ts
// ...
export const { BlocProvider, useBloc, useWeakBloc } = setupBlocs({
foobar: (arg: number) => new BlocNameBloc()
})
// ---------------------------------------------------
// SomeComponent.ts
...
useWeakBloc("foobar")() // => undefined
useBloc("foobar")(42) // => BlocNameBloc
useWeakBloc("foobar")() // => BlocNameBloc

Summary

For some reason, BLoC is more popular than Redux among Flutter developers. If you are looking for an alternative for Redux, you can try this approach however I would be careful with using it in production.

--

--