Here is the way to follow to setup La Taverne
on your app:
reactions
: the way your store must reduce actions.{dispatch, taverne}
through the provider <Taverne>
.pour
data in your containersdispatch
actions to trigger reactions
.In the following, let's illustrate how to use Taverne
with:
Items
and its fetch functioncontainer
plugged to this store,component
rendering the list of items.Illustration will be marked with 🔍
You'll have to define a barrel
with
const items = {
initialState: {},
reactions: []
};
export default items;
You should use one barrel
for each feature.
La Taverne
will:
reactions
,Here is the example for our illustrating items
/* ./actions/items.js */
export const FETCH_ITEMS = 'FETCH_ITEMS';
/* ./barrels/items.js */
import {FETCH_ITEMS} from '../actions/items.js';
import apiCall from './fetch-items.js';
const initialState = {items: null};
const fetchItems = {
on: FETCH_ITEMS,
perform: async (payload, dispatch, getState) => {
// This function will be called whenever {type:FETCH_ITEMS} is dispatched.
// `getState` is provided here for convenience, to access the current store state.
const items = await apiCall(payload);
return items;
},
reduce: (draft, payload) => {
// 'reduce' will be called after `perform` is over.
// 'perform' returns the items, so here payload === items
draft.items = payload;
}
};
const reactions = [fetchItems];
export default {initialState, reactions};
Once all reducers are ready, instanciate and pass {dispatch, taverne}
to the <Taverne>
provider.
🔍 Example:
/* ./index.js */
import React from 'react';
import {render} from 'react-dom';
import {Taverne} from 'taverne/hooks';
import items from './barrles/items.js';
import anyOtherStuff from './barrels/whatever.js';
const barrels = {
items,
anyOtherStuff
};
const {dispatch, taverne} = createLaTaverne(barrels);
render(
<Taverne dispatch={dispatch} taverne={taverne}>
<App />
</Taverne>,
container
);
La Taverne
pours data for you by:
The pour
hook allows to listen to changes in your global state, use the part you need in your local props.
That's the mapStateToProps
if you come from Redux.
🔍 Here is the example for our illustrating items
:
/* ./features/items/container.js */
import React from 'react';
import ItemsComponent from './component';
const ItemsContainer = props => {
const {pour} = useTaverne();
const items = pour('items');
return <ItemsComponent items={items} />;
};
To listen to specific changes in the global state, and update your local props only on those changes, you can use many kinds of parameters to pour()
(see the advanced section).
Use prop drilling
from your containers to your components: pass functions dispatching the actions
import {SELECT_ITEM} from './actions/items.js';
const ItemsContainer = props => {
const {dispatch} = useTaverne();
const selectItem = id => () => {
dispatch({
type: SELECT_ITEM,
payload: {itemId: id}
});
};
return <ItemsComponent selectItem={selectItem} />;
};
The whole point of Taverne
is to be able to perform extremely local rendering.
So, rather than the listening for the whole state updates, you can update rendering depending on specific updates in your global state.
To do so, specify the props
mapping you want to listen for changes, telling corresponding paths in your state.
const Container = () => {
const {pour} = useTaverne();
const foo = pour('path.to.anything.within.your.store');
return <Component foo={foo} />;
};
This way, on every store update, specific props will be extracted for the components.
If those props don't change, the store won't notify your container, preventing a re-rendering: this will allow accurate local rendering from a global app state.
You can map a many props in one single pouring:
const ItemsContainer = props => {
const {pour} = useTaverne();
const {items, other} = pour({
items: 'items',
other: 'plop.plip.plup'
});
return <ItemsComponent items={items} other={other} />;
};
You can also use your state to read paths depending on your state:
const BookContainer = props => {
const {pour} = useTaverne();
const book = pour(state => ({
book: `shelves.${state.selectedShelfId}.books.${state.selectedBookId}`
}));
return <BookComponent book={book} />;
};
Cheers 🍻 !