https://github.com/uralys/taverne
⛵ Yet another Redux alternative
https://github.com/uralys/taverne
flux flux-architecture hooks immer mobx-react-alternative react react-hooks react-state-management react-stores redux-alternative use-state
Last synced: 6 months ago
JSON representation
⛵ Yet another Redux alternative
- Host: GitHub
- URL: https://github.com/uralys/taverne
- Owner: uralys
- License: mit
- Created: 2020-12-29T11:12:04.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2025-03-20T10:49:35.000Z (7 months ago)
- Last Synced: 2025-04-11T21:05:10.607Z (6 months ago)
- Topics: flux, flux-architecture, hooks, immer, mobx-react-alternative, react, react-hooks, react-state-management, react-stores, redux-alternative, use-state
- Language: JavaScript
- Homepage: https://taverne.uralys.com
- Size: 3.4 MB
- Stars: 12
- Watchers: 1
- Forks: 0
- Open Issues: 6
-
Metadata Files:
- Readme: readme.md
- Funding: .github/FUNDING.yml
- License: license
Awesome Lists containing this project
README
# La Taverne
`La Taverne` is an elementary [Flux](https://facebook.github.io/flux/docs/in-depth-overview) implementation to manage a global app state.
It provides an optional, yet easy integration with React using custom **hooks**.

## 🕵️ Demo
- Try live on
- Demo sources:## 📦 installation
```sh
> npm i --save taverne
```## 🐿️ Instanciate your taverne with your barrels
Once your barrels are ready, you can instanciate your `taverne` and `dispatch`:
```js
import createLaTaverne from 'taverne';
import books from './barrels/books';
import potions from './barrels/potions';
import handcrafts from './barrels/handcrafts';const {dispatch, taverne} = createLaTaverne({
books,
potions,
handcrafts
});
```## 🧬 Create a barrel
A "Barrel" is an `initialState` and a list of `reactions`.
```js
const ADD_BOOK = 'ADD_BOOK';const addBook = {
on: ADD_BOOK,
reduce: (state, payload) => {
const {book} = payload;
state.entities.push(book);
}
};export default {
initialState: {entities: []},
reactions: [addBook]
};export {ADD_BOOK};
```## 🧚 Reactions
- A `reaction` will be triggered when an action is dispatched with `action.type` === `on`.
```js
const doSomethingWithThisBarrel = {
on: 'ACTION_TYPE',
reduce: (state, payload) => {
/*
Just update the state with your payload.
Here, `state` is the draftState used by `Immer.produce`
You taverne will then record your next immutable state.
*/
state.foo = 'bar';
},
perform: (parameters, dispatch, getState) => {
/*
Optional sync or async function.
It will be called before `reduce`When it is done, reduce will receive the result in
the `payload` parameter.You can `dispatch` next steps from here as well
*/
}
};
```- `reduce` is called using `Immer`, so mutate the `state` exactly as you would with the `draftState` parameter in [produce](https://immerjs.github.io/immer/docs/produce).
- If you have some business to do before reducing, for example calling an API, use the `perform` function, either `sync` or `async`.
Then `reduce` will be called with the result once it's done.
## 🎨 React integration
`La Taverne` has a context Provider `` which provides 2 utilities:
- the `pour` hook to access your global state anywhere
- the `dispatch` function```js
/* src/app.js */
import React from 'react';
import {render} from 'react-dom';
import {Taverne} from 'taverne/hooks';render(
,
container
);
``````js
/* src/feature/books/container.js */
import {useTaverne} from 'taverne/hooks';const BooksContainer = props => {
const {dispatch, pour} = useTaverne();
const books = pour('books');return ;
};
```See the complete React integration [steps here](docs/react.md).
You can "pour" specific parts of the "taverne", to allow [accurate local rendering](docs/react.md#-advanced-usage) from your global app state.
## 🔆 Middlewares
You can create more generic middlewares to operate any actions.
Your middlewares must implement `onDispatch: (action, dispatch, getState) => {}`
```js
const customMiddleware = taverne => {
const instance = {
onDispatch: (action, dispatch, getState) => {}
};return instance;
};
```Then instanciate `La Taverne` with your list of middlewares as 2nd parameter:
```js
const {dispatch, taverne} = createLaTaverne(barrels, [customMiddleware]);
```example: plugging the [redux devtools extension](https://github.com/reduxjs/redux-devtools) with this [middleware](src/middlewares/devtools.js)
## 🐛 Redux devtools
Using devtools with `La Taverne` provides debugging without losing performance:
- gathered debounced actions
- nested actions
- optional state filtering to improve performance
```js
import createLaTaverne from 'taverne';
import {createDevtools} from 'taverne/middlewares';
import books from './barrels/books';const devtools = createDevtools();
const {dispatch, taverne} = createLaTaverne({books}, [devtools]);
```When your app state is too big, you'll hit performance issues with Redux dev tools.
In this case you may need to skip part of state from tracking;
```js
const devtools = createDevtools({
applyStateFiltering? : state => ({
...state,
hugeObject: ''
})
});
```## 🏗️ development
- 📓 Few local dev [notes](docs/dev.md) for the curious ones.
- ✅ Issues and PR Welcomed!