React Beaker Store
Intuitive and reactive state management library for React apps.
Installation
npm install react-beaker-store
Usage
Create a Beaker Store
You can create as many beaker stores as you want, it is recommended for each to be defined in a separate file:
const beaker = createBeaker({
state: {
counter: 0,
someData: ''
},
actions: {
increment(){
this.state.counter += 1;
},
setSomeData(newSomeData){
this.state.someData = newSomeData;
}
}
});
Connect a Beaker Store to a React component
You need to add useBeakerState() hook to your components to start reacting.
function MyComponent() {
const { counter } = useBeakerState(beaker);
return (
<button onClick={beaker.actions.increment}>
{counter}
</button>
);
}
Using Async Actions
In the following snippet you can find an example of how async actions can be implemented:
const beaker = createBeaker({
state: {
loading: false,
error: null,
result: null
},
actions: {
async loadData(){
try {
this.state.loading = true;
const response = await fetch('https://api.example.com/v1/some-data');
if (!response.ok) throw Error(`Received response with status code ${response.status}`)
this.state.result = await response.json();
} catch (error) {
this.state.error = error;
} finally {
this.state.loading = false;
}
}
}
});
function MyComponent() {
const { loading, error, result } = useBeakerState(beaker);
useEffect(() => {
beaker.actions.loadData();
}, []);
return (
<div>
{/* show the error message in case error occurs */}
{error && <div>Unfortunately an error occurred</div>}
{/* show a loading message while loading */}
{loading && <div>The content is loading...</div>}
{/* when the result is ready, display it! */}
{result && <div>{result}</div> }
</div>
);
}
Use Beaker Store from anywhere in your code
Beakers not only work with React components, you can change their state or call their actions from anywhere in your application.
async function getDataFromApi() {
const response = await fetch('https://api.example.com/v1/some-data');
const json = await response.json();
beaker.actions.setSomeData(json.data);
}
Manually committing changes to trigger required updates to components.
Imagine you want to give progressive insights about the state of a process happening in your app. Beakers are flexible enough to help you with that!
async function getDataFromApi() {
beaker.state.loading = true;
beaker.commit();
const response = await fetch('https://api.example.com/v1/some-data');
const json = await response.json();
beaker.state.someData = json.data;
beaker.state.loading = false;
beaker.commit();
}
Listening to Beaker Store changes outside of React components
What if you needed to run a process when some state is met, but that code simply does not belong inside a React component? Beaker got you covered!
function validateState() {
}
beaker.subscribe(validateState);
beaker.unsubscribe(validateState);
FAQ
Why should I use react-beaker-store instead of redux, mobx, recoil or the react context api?
You are free to use any solution you prefer, but we would recommend it for:
- Developers creating new apps and looking to keep their code simple and understandable to other devs.
- Developers building code bases which must be scalable and flexible to changes from many people.
- Developers who want to avoid excessively large and hard to maintain boilerplates in their code.
- Developers wanting to avoid complex configurations in their apps which are easy to break or misuse by other devs.
How does react-beaker-store really work?
react-beaker-store is powered by Immer.
What inspired react-beaker-store?
The idea for this project came thanks to pinia, which is fantastic state management solution for Vue apps, if you already know pinia you can't unsee the similarities.
Can I contribute to this project?
Off course! any ideas, improvements and pull requests are welcome!
License
MIT