CreateSyncTile API
CreateSyncTile is very similar to createTile, but does not provide asynchronous functionality. Because of that, it is a little bit simpler – there is no caching, and only two constants – SET and RESET.
The basic sync tile will look like that:
import { createSyncTile } from 'redux-tiles';
const nofitications = createSyncTile({
type: ['ui', 'notifications'],
// actually, if you are fine just passing params into the store, you
// can omit it – default function has exactly this functionality
fn: ({ params }) => params,
});
Because there is no async actions under the hood, there is also no related data structure – what you return from your function, will go straight to the state (and will be returned from selector's function).
Let's take a look at a little bit more extensive example:
import { createSyncTile } from 'redux-tiles';
const chooseParams = createSyncTile({
// type works exactly as in `createTile` – will be nested in store,
// and `createEntities` will put it under this namespace in actions/selectors
type: ['ui', 'params'],
// while you have to perform only sync operations to return some value,
// you can dispatch other actions
// this function will be available under actions.ui.params
// so, for instance, you can do self-closing notifications (e.g. dispatching
// the same tile action), or send some tracking – but be careful, it is
// very easy to introduce some race-conditions – for complex async stuff
// consider using something like RxJS or redux-saga
fn: ({ params }) => {
return params.data;
},
// alternatively, if you perform some actions on existing data,
// it might be useful to write more declarative actions
// they have exactly the same signature and dispatch returned data
// to the tile; they will be available under
// actions.ui.params.add and actions.ui.params.remove
fns: {
add: ({ params, selectors, getState}) => {
const list = selectors.notifications(getState(), params);
return list.concat(params);
},
remove: ({ params, selectors, getState}) => {
const list = selectors.notifications(getState(), params);
return list.filter(({ id }) => id !== params.id);
},
},
// same as in `createTile` – separate data, so they will stored inside
// store independently
nesting: ({ type }) => [type],
// initial state to put into reducer. If you store list of elements,
// and don't want to check whether type of data is array or object,
// use this property
initialState: [],
});
Example
Let's create a tile for todoMVC application. We have to perform a lot of listing list of all notifications which were triggered. We won't remove them here for the sake of simplicity, but we can easily add it with filtering.
import { createSyncTile } from 'redux-tiles';
export const todosTile = createSyncTile({
type: ['todos', 'list'],
// to create more declarative function names, we will use
// fns property. all functions from this object will be
// attached to main action, so they will be available under
// actions.todos.list.%function%
fns: {
// this function will be available under
// actions.todos.list.add
add: ({ params, selectors, getState }) => {
const list = selectors.todos.list(getState());
const newItem = {
...params,
completed: false,
id: Math.random(),
};
return list.concat(newItem);
},
// this function will be available under
// actions.todos.list.remove
remove: ({ params, selectors, getState }) => {
const list = selectors.todos.list(getState());
return list.filter(item => item.id !== params.id);
},
// this function will be available under
// actions.todos.list.toggle
toggle: ({ params, selectors, getState }) => {
const list = selectors.todos.list(getState());
return list.map(todo => todo.id === params.id
? { ...todo, completed: !todo.completed }
: todo
);
}
},
// we state initial state as [], so we don't have to check
// the type of data (we are sure that it will be an array)
initialState: [],
});