Gathering detailed insights and metrics for redux-symbiote
Gathering detailed insights and metrics for redux-symbiote
Gathering detailed insights and metrics for redux-symbiote
Gathering detailed insights and metrics for redux-symbiote
npm install redux-symbiote
Typescript
Module System
Node Version
NPM Version
JavaScript (81.21%)
TypeScript (18.79%)
Total Downloads
91,649
Last Day
71
Last Week
230
Last Month
1,260
Last Year
14,299
MIT License
163 Stars
95 Commits
9 Forks
5 Watchers
2 Branches
8 Contributors
Updated on Aug 01, 2024
Latest Version
3.4.0
Package Id
redux-symbiote@3.4.0
Unpacked Size
32.90 kB
Size
8.89 kB
File Count
11
NPM Version
6.9.0
Node Version
10.16.3
Cumulative downloads
Total Downloads
Last Day
82.1%
71
Compared to previous day
Last Week
-36.8%
230
Compared to previous week
Last Month
-16.7%
1,260
Compared to previous month
Last Year
18.1%
14,299
Compared to previous year
2
Write your actions and reducers without pain
1import { createSymbiote } from 'redux-symbiote' 2 3 4const initialState = { 5 error: null, 6 accounts: [], 7 loading: false, 8} 9 10const symbiotes = { 11 accounts: { 12 loading: { 13 start: (state) => ({ ...state, loading: true }), 14 failed: (state, error) => ({ ...state, loading: false, error }), 15 finish: (state, accounts) => ({ ...state, loading: false, accounts }), 16 }, 17 }, 18} 19 20export const { actions, reducer } = createSymbiote(initialState, symbiotes)
Also you can use CommonJS:
1const { createSymbiote } = require('redux-symbiote') 2 3// ...
1function createSymbiote(
2 initialState,
3 symbiotes,
4 ?namespace = ''
5)
1createSymbiote(initialState, {
2 actionType: actionReducer,
3 nestedType: {
4 actionType: nestedActionReducer,
5 }
6})
Example:
1const initialState = { value: 1, data: 'another' } 2 3const symbiotes = { 4 increment: (state) => ({ ...state, value: state.value + 1 }), 5 decrement: (state) => ({ ...state, value: state.value - 1 }), 6 setValue: (state, value) => ({ ...state, value }), 7 setData: (state, data) => ({ ...state, data }), 8 concatData: (state, data) => ({ ...state, data: data + state.data }), 9} 10 11export const { actions, reducer } = createSymbiote(initialState, symbiotes) 12 13dispatch(actions.increment()) // { type: 'increment' } 14dispatch(actions.setValue(4)) // { type: 'setValue', payload: [4] } 15dispatch(actions.decrement()) // { type: 'decrement' } 16dispatch(actions.setData('bar')) // { type: 'setData', payload: ['bar'] } 17dispatch(actions.concatData('foo ')) // { type: 'concatData', payload: ['foo '] } 18 19// State here { value: 3, data: 'foo bar' }
When you call actions.setValue
symbiote calls your action handler with previousState and all arguments spreaded after state.
1const initialState = { value: 1, data: 'another' } 2 3const symbiotes = { 4 value: { 5 increment: (state) => ({ ...state, value: state.value + 1 }), 6 decrement: (state) => ({ ...state, value: state.value - 1 }), 7 }, 8 data: { 9 set: (state, data) => ({ ...state, data }), 10 concat: (state, data) => ({ ...state, data: data + state.data }), 11 }, 12} 13 14export const { actions, reducer } = createSymbiote(initialState, symbiotes) 15 16dispatch(actions.value.increment()) // { type: 'value/increment' } 17dispatch(actions.value.decrement()) // { type: 'value/decrement' } 18dispatch(actions.data.set('bar')) // { type: 'data/set', payload: ['bar'] } 19dispatch(actions.data.concat('foo ')) // { type: 'data/concat', payload: ['foo '] }
Third parameter in createSymbiote
is optional string
or object
.
If string
passed, symbiote converts it to { namespace: 'string' }
.
Object has optional properties:
namespace
is string
— set prefix for each action typedefaultReducer
is (previousState, action) -> newState
— called instead of return previous stateseparator
is string
— change separator of nested action types (default /
)You can use action as action type in classic reducer or in handleAction(s)
in redux-actions
1import { handleActions } from 'redux-actions' 2import { createSymbiote } from 'redux-symbiote' 3 4const initialState = { /* ... */ } 5 6const symbiotes = { 7 foo: { 8 bar: { 9 baz: (state, arg1, arg2) => ({ ...state, data: arg1, atad: arg2 }), 10 }, 11 }, 12} 13 14const { actions } = createSymbiote(initialState, symbiotes) 15 16const reducer = handleActions({ 17 [actions.foo.bar.baz]: (state, { payload: [arg1, arg2] }) => ({ 18 ...state, 19 data: arg1, 20 atad: arg2, 21 }), 22}, initialState)
createSymbiote
returns object with actions
and reducer
.
Created reducer already handles created actions. You don't need to handle actions from symbiote.
1// accounts.js 2export const { actions, reducer } = createSymbiote(initialState, symbiotes, options) 3 4// reducer.js 5import { reducer as accounts } from '../accounts/symbiote' 6// another imports 7 8export const reducer = combineReducers({ 9 accounts, 10 // another reducers 11})
Redux recommends creating constants, action creators and reducers separately.
1const ACCOUNTS_LOADING_START = 'ACCOUNTS_LOADING_START' 2const ACCOUNTS_LOADING_FAILED = 'ACCOUNTS_LOADING_FAILED' 3const ACCOUNTS_LOADING_FINISH = 'ACCOUNTS_LOADING_FINISH' 4 5 6export function loadingStart() { 7 return { 8 type: ACCOUNTS_LOADING_START, 9 } 10} 11 12export function loadingFailed(error) { 13 return { 14 type: ACCOUNTS_LOADING_FAILED, 15 payload: { 16 error, 17 }, 18 } 19} 20 21export function loadingFinish(accounts) { 22 return { 23 type: ACCOUNTS_LOADING_FINISH, 24 payload: { 25 accounts, 26 }, 27 } 28} 29 30const initialState = { 31 error: null, 32 accounts: [], 33 loading: false, 34} 35 36export function accountsReducer(state = initialState, action) { 37 switch (action.type) { 38 case ACCOUNTS_LOADING_START: 39 return Object.assign({}, state, { 40 loading: true, 41 }) 42 43 case ACCOUNTS_LOADING_FAILED: 44 return Object.assign({}, state, { 45 loading: false, 46 error: action.payload.error, 47 }) 48 49 case ACCOUNTS_LOADING_FINISH: 50 return Object.assign({}, state, { 51 loading: false, 52 accounts: action.payload.accounts, 53 }) 54 } 55 56 return state 57}
So much boilerplate.
Let's look at redux-actions.
1import { createActions, handleActions, combineActions } from 'redux-actions' 2 3 4export const actions = createActions({ 5 accounts: { 6 loading: { 7 start: () => ({ loading: true }), 8 failed: (error) => ({ loading: false, error }), 9 finish: (accounts) => ({ loading: false, accounts }), 10 }, 11 }, 12}).accounts 13 14const initialState = { 15 error: null, 16 accounts: [], 17 loading: false, 18} 19 20export const accountsReducer = handleActions({ 21 [combineActions(actions.loading.start, actions.loading.failed, actions.loading.finish)]: 22 (state, { payload: { loading } }) => ({ ...state, loading }), 23 24 [actions.loading.failed]: (state, { payload: { error } }) => ({ ...state, error }), 25 26 [actions.loading.finish]: (state, { payload: { accounts } }) => ({ ...state, accounts }), 27}, initialState)
But we have some duplicate in action creators properties and reducer.
Let's rewrite it to redux-symbiote:
1import { createSymbiote } from 'redux-symbiote' 2 3const initialState = { 4 error: null, 5 accounts: [], 6 loading: false, 7} 8 9const symbiotes = { 10 start: (state) => ({ ...state, loading: true }), 11 finish: (state, { accounts }) => ({ ...state, loading: false, accounts }), 12 failed: (state, { error }) => ({ ...state, loading: false, error }), 13} 14 15export const { actions, reducer: accountsReducer } = 16 createSymbiote(initialState, symbiotes, 'accounts/loading')
That's all. accounts/loading
is an optional namespace for actions types.
To reduce noise around loading actions try symbiote-fetching
.
Thanks goes to these wonderful people (emoji key):
Sergey Sova 📖 💻 💡 🤔 ⚠️ | Arutyunyan Artyom 👀 🤔 🐛 💻 | Igor Kamyshev 📦 ⚠️ | Ilya 🐛 | Ivanov Vadim 📖 | Аnton Krivokhizhin 📦 🚇 | Viacheslav 🤔 👀 |
Dmitri Razin 🐛 🎨 | Surgie Finesse 💻 |
This project follows the all-contributors specification. Contributions of any kind welcome!
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 4/16 approved changesets -- score normalized to 2
Reason
project is archived
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
53 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More