Product
Socket Now Supports uv.lock Files
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.
bloc-react
Advanced tools
BLoC state management for react
Typescript implementation for react heavily inspired by flutter_react - https://bloclibrary.dev The BLoC Pattern (Business Logic Component) is a battle-tested design pattern for state management coming from Flutter and Dart. It tries to separate business logic from UI as much as possible while still being simple and flexible.
$ npm i bloc-react
# or
$ yarn add bloc-react
// CounterCubit.ts
export default class CounterCubit extends Cubit<number> {
increment = (): void => this.emit(this.state + 1)
}
useBloc
from it// state.ts
const state = new BlocReact([new CounterCubit(0)]);
export const { useBloc } = state;
// CounterButton.tsx
const Counter: FC = (): ReactElement => {
const [value, { increment }] = useBloc(CounterCubit);
return <button onClick={() => increment()}>count is: {value}</button>;
}
The BlocReact
class handles the global state and manages all communication between individual BLoCs.
When initializing pass all the BLoCs for the global state in an array as first parameter.
const state = new BlocReact([new MyBloc(), new MyCubit()]);
You can add an observer to all state changes global and local
state.observer = new BlocObserver({
// onChange is called for all changes (Cubits and Blocs)
onChange: (bloc, event) => console.log({bloc, event}),
// onTransition is called only when Blocs transition from one state to another,
// it is not called for Cubits
onTransition: (bloc, event) => console.log({bloc, event}),
});
A Cubit is a simplified version Bloc
class. Create your custom Cubit by extending the Cubit
class, pass the initial state to the super
constructor.
The Cubits' state is updated by calling the this.emit
method with the new state.
export default class CounterCubit extends Cubit<number> {
constructor() {
super(0);
}
increment = (): void => {
this.emit(this.state + 1);
};
}
In the react component you can then call the public methods like increment
in this example
const Counter: FC = (): ReactElement => {
const [value, { increment }] = useBloc(CounterCubit);
return <button onClick={() => increment()}>count is: {value}</button>;
}
Most of the time the Cubit
class will be the easiest way to manage a piece of state but for the more critical parts of your application where there can be various reasons why the state changes to the same value, for example user authentication. It might be nice to know if the user got logged out because an error occurred, the token expired or if they just clicked on the logout button.
This is especially helpful when debugging some unexpected behaviour.
In the BlocObserver
you can then use the onTransition
to see why the state changes, it will pass the previous state, the event itself and the next state.
export enum AuthEvent {
unknown = "unknown",
authenticated = "authenticated",
unauthenticated = "unauthenticated",
}
export default class AuthBloc extends Bloc<AuthEvent, boolean> {
constructor() {
super(false)
this.mapEventToState = (event) => {
switch (event) {
case AuthEvent.unknown:
return false;
case AuthEvent.unauthenticated:
return false;
case AuthEvent.authenticated:
return true;
}
};
}
In your app you can then update the state by "adding" an event. Use the useBloc
hook to get access to the BLoC class and add an event.
const Component: FC = (): ReactElement => {
const [state, bloc] = useBloc(AuthBloc);
return <>
{state === true && <Button onClick={() => bloc.add(AuthEvent.unauthenticated)}>Logout</Button>}
</>
}
The main way to use the BLoCs in your UI will be with the useBloc
hook, the first parameter is the class constructor of the Bloc you want to use.
The second parameters are options to configure how that hook behaves.
The return value of useBloc
is an array of two items, the first is the state of your BLoC, the second is the class which controls that part of the state.
Decide whether the returned state value should be updated or not. Will have no effect if subscribe
is false.
const [state] = useBloc(CounterCubit, {
// `state` is only updated if the count is even
shouldUpdate: (event) => event.nextState % 2 === 0,
});
If false
, the returned state will never be updated. Use this if you only need access to the BLoC class.
// we only need the `bloc` to call `bloc.increment` for example.
const [, bloc] = useBloc(CounterCubit, {
subscribe: false,
});
Create a local state on demand with the BlocProvider
. A context is created that then is available in the children of the BlocProvider. When the global and the local state both have the same Bloc, the local one is used.
In the bloc
property, pass a function that returns a new instance of the BLoC you want to provide. Or pass the BLoC directly.
const Counter: FC = (): ReactElement => {
return <div>
<BlocProvider<CounterCubit>
bloc={() => new CounterCubit()}
// bloc={new CounterCubit()} // can also be passed directly
>
<Counter />
</BlocProvider>
</div>;
}
If you can't or don't want to use the useBloc
hook to access the bloc state you an alternatively opt for the BlocBuilder
which is just a Higher Order Component that uses useBloc under the hood.
The blocClass
property takes a class constructor of a Bloc and provides an instance of that class in the builder
property.
The values passed into the callback for builder
are the same you would get from the useBloc
hook.
You can also pass the shouldUpdate
property to the BlocBuilder
which works the same as the option of the same name for the useBloc
hook.
class Counter extends Component {
render() {
return <BlocBuilder<CounterCubit>
blocClass={CounterCubit}
builder={([value, { increment }]) => (
<div>
<Button onClick={() => increment()}>{value}</Button>
</div>
)}
/>;
}
}
The BlocBuilder can also be used to set the scope which can help performance when you don't want to rerender the whole component every time the state changes.
FAQs
Unknown package
The npm package bloc-react receives a total of 0 weekly downloads. As such, bloc-react popularity was classified as not popular.
We found that bloc-react demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.
Research
Security News
Socket researchers have discovered multiple malicious npm packages targeting Solana private keys, abusing Gmail to exfiltrate the data and drain Solana wallets.
Security News
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.