captain-redux
v0.1.3
Published
Easy and convenient redux
Downloads
5
Readme
Captain-redux
it redux without reducers.
Captain most simple and fastest for developing store container based on redux.
How It Works
This library allows you use redux without constans. Actions it's really actions, they do what you want and not need create functions which just return object acceptable for dispatching.
Usage
Let's take a look at a simple example.
import * as redux from "redux"
import captain from "captain-redux"
//bind captain and redux
let {createStore, createAction } = captain(redux);
//create store with initial state
let store = createStore({
counter: 1,
user: {
post: "Capitan",
firstName: "Jack",
lastName: "Sparrow"
}
});
//create reducers in actions
//in captain-redux all actions is functions which recive (state, ....args)
//args - it all parameters passed during dispath
let setCounter = createAction((state,counter) => ({ counter }));
//action reurns only changed field
store.dispatch(setCounter(3));
console.log(store.getState());
//{
// counter: 3,
// user: {
// post: "Capitan",
// firstName: "Jack",
// lastName: "Sparrow"
// }
//}
setFirstName = createAction((state,firstName) => ({ firstName }));
//define tell to store what action can change the specified property
captain.define({
user: setFirstName
});
store.dispatch(setFirstName("Bob"));
console.log(store.getState());
//{
// counter: 3,
// user: {
// post: "Capitan",
// firstName: "Bob",
// lastName: "Sparrow"
// }
//}
Installation
npm install --save captain-redux
Tutorial
Captain apply you control state of you app just write only business logic
CreateAction is easy way change state of you app
//actions.js
import { createAction } from "captain-redux"
//action it function which recive state
//...and parameters puttet when action will be performed
export let addTodo = createAction((state, id, text) => ({
todos: [...state.todos, { id, text }]
})
);
//action return only changed part of state
Let's write default state
//state.js
export default const initState = {
nameApp: "Todo list",
todos: [
{
id: 1,
text: "understand captain"
}
]
};
And create store
//store.js
import * as redux from 'redux'
import captain from "captain-redux"
import initState from './state.js'
let { createStore } = captain(redux);
export default let store = createStore(initState);
It's all! We can change state our app
//index.js
import store from './store.js'
import { addTodo } from './actions.js'
store.dispatch(addTodo(2,"drink rum"));
console.log(store.getState());
//{
// nameApp: "Todo list",
// todos: [
// {
// id: 1,
// text: "understand captain"
// },
// {
// id: 2,
// text: "drink rum"
// }
// ]
//}
But why we always write id of todo himself? Go add counter of todo in our state.
//state.js
export default const initState = {
nameApp: "Todo list",
countOfTodos: 1,
todos: [
{
id: 1,
text: "understand captain"
}
]
};
And change action
//actions.js
//...
export let addTodo = createAction((state, text) => ({
countOfTodos: state.countOfTodos+1
todos: [...state.todos, { state.countOfTodos+1, text }]
})
);
It work, but we can do our state more logical. Let's just join todos and their count in one ob ject.
//state.js
export default const initState = {
nameApp: "Todo list",
data: {
countOfTodos: 1,
todos: [
{
id: 1,
text: "understand captain"
}
]
}
};
And tell our action where him need change state
//actions.js
import { createAction, define } from "captain-redux"
import initState from "state.js"
let addTodo = createAction((state, text) => ({
countOfTodos: state.countOfTodos+1
todos: [...state.todos, { state.countOfTodos+1, text }]
})
);
//we can tell state where action can change him
define(initState,{
data: addTodo
});
export addTodo;
Let's see how it will work
//index.js
import store from './store.js'
import { addTodo } from './actions.js'
store.dispatch(addTodo("drink more rum"));
console.log(store.getState());
//{
// nameApp: "Todo list",
// todos: [
// {
// id: 1,
// text: "understand captain"
// },
// {
// id: 2,
// text: "drink more rum"
// }
// ]
//}
API
###define Receive one object with names of fields repeating state and values is actions which need process this fields. Example
import {define} from 'captain-redux'
import {setDate, addUser, buy, sell} from './actions.js'
import initState from './state.js'
console.log(initState);
//{
// users: {
// count: 42,
// base: [ {name: "Jack" }, ...]
// },
// goods:{
// count: 150,
// base: [ {name: "phone", price: 300 }, ...]
// },
// date: '14.11.17',
// money: "1 million"
//}
define(initState,{
users: addUser,
goods: [buy, sell],
//date: setDate - it's not work, becouse date not object
setDate // it action will be all state (default)
});
###createAsyncAction Synchronous actions not enough in real app, but you can create asynchronous actions.
//actions.js
import { createAction, createAsyncAction } from "captain-redux"
let changeState = createAction(state => ({ data: state.data + 1 });
//asynchonous actions creating like synchronous, but first argument give dispatch function
export const doSomthingAsync = createAsyncAction(({ dispatch },num) =>{
for(let i = 0; i < num; i++)
setTimeout(() => dispatch(changeState()), 500);
});
And we can use this action like synchronous
//index.js
import redix from "redux"
import captain from 'captain-redux'
import { doSomethingAsync } from './actions.js'
captain(redux);
let store = captain.createStore({
data: 1
});
store.dispatch(doSomethingAsync(3));
setTimeout(() =>
console.log(store.getState())
, 2000);
//{
// data: 4
//}
Also createAsyncAction give getState in first argument
//actions.js
import { createAsyncAction } from "captain-redux"
//asynchonous actions creating like synchronous, but first argument give dispatch function
export const doSomthingAsync = createAsyncAction(({ dispatch, getState },num) =>{
for(let i = 0; i < num; i++)
setTimeout(() => console.log(getState()), 500;
});
And then you can return promise from your action to continue use it in current code context
//actions.js
import { createAsyncAction } from "captain-redux"
//asynchonous actions creating like synchronous, but first argument give dispatch function
export const doAsync = createAsyncAction(({ dispatch, getState },num) => new Promise(resolve => {
//do something...
resolve();
}));
//index.js
import redix from "redux"
import captain from 'captain-redux'
import { doAsync } from './actions.js'
captain(redux);
let store = captain.createStore({
//...
});
store.dispatch(doAsync())
.then(() => console.log("successfully complated"));
//...
//successfully complated
##Migration guide From redux to captain
Just replace it
import {creteStore, applyMiddleware, compose} from 'redux'
...
...on it
import * as redux from 'redux'
import captain from 'captain-redux'
let {creteStore, applyMiddleware, compose} = captain(redux)
...