All Projects → unirakun → k-redux-factory

unirakun / k-redux-factory

Licence: MIT License
Factory of Redux reducers and their associated actions and selectors.

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to k-redux-factory

redux-reducer-async
Create redux reducers for async behaviors of multiple actions.
Stars: ✭ 14 (-22.22%)
Mutual labels:  actions, reducer, action, reducers
actions
Collection of repetitive GitHub Actions
Stars: ✭ 12 (-33.33%)
Mutual labels:  actions, action
rubocop-linter-action
Rubocop Linter Action: A GitHub Action to run Rubocop against your code!
Stars: ✭ 86 (+377.78%)
Mutual labels:  actions, action
riduce
Get rid of your reducer boilerplate! Zero hassle state management that's typed, flexible and scalable.
Stars: ✭ 14 (-22.22%)
Mutual labels:  reducer, reducers
clojure-dependency-update-action
A simple GitHub Actions job to create Pull Requests for outdated dependencies in clojure projects
Stars: ✭ 37 (+105.56%)
Mutual labels:  actions, action
deployer-php-action
Deploy PHP projects using Deployer from Github Actions
Stars: ✭ 57 (+216.67%)
Mutual labels:  actions, action
assign-one-project-github-action
Automatically add an issue or pull request to specific GitHub Project(s) when you create and/or label them.
Stars: ✭ 140 (+677.78%)
Mutual labels:  actions, action
dart-package-publisher
Action to Publish Dart / Flutter Package To https://pub.dev When you need to publish a package, just bump the version in pubspec.yaml
Stars: ✭ 45 (+150%)
Mutual labels:  actions, action
gh-action-community
GitHub Action for the Community, from welcoming first timers to badges
Stars: ✭ 24 (+33.33%)
Mutual labels:  actions, action
RxReduxK
Micro-framework for Redux implemented in Kotlin
Stars: ✭ 65 (+261.11%)
Mutual labels:  reducer, action
action-sync-node-meta
GitHub Action that syncs package.json with the repository metadata.
Stars: ✭ 25 (+38.89%)
Mutual labels:  actions, action
redux-lightweight
Write one business logic instead of writing actions, action types and reducers
Stars: ✭ 41 (+127.78%)
Mutual labels:  reducer, action
setup-hashlink
A github action to install and setup Hashlink
Stars: ✭ 13 (-27.78%)
Mutual labels:  actions, action
hermes-js
Universal action dispatcher for JavaScript apps
Stars: ✭ 15 (-16.67%)
Mutual labels:  reducer, action
setup-jdk
(DEPRECATED) Set up your GitHub Actions workflow with a specific version of AdoptOpenJDK
Stars: ✭ 32 (+77.78%)
Mutual labels:  actions, action
jest-github-action
Jest action adding checks with annotations to your pull requests and coverage table as comments
Stars: ✭ 134 (+644.44%)
Mutual labels:  actions, action
cra-redux-boilerplate
⚛️🔨create-react-app application with redux and another cool libraries to make your life easier.
Stars: ✭ 15 (-16.67%)
Mutual labels:  selector, reducer
actions
Set of actions for implementing CI/CD with werf and GitHub Actions
Stars: ✭ 67 (+272.22%)
Mutual labels:  actions, action
chrome-extension-upload
upload & publish extensions to the Chrome Web Store.
Stars: ✭ 35 (+94.44%)
Mutual labels:  actions, action
ssh2actions
Connect to GitHub Actions VM via SSH for interactive debugging
Stars: ✭ 62 (+244.44%)
Mutual labels:  actions, action

k-redux-factory

Factory of Redux reducers and their associated actions and selectors.

Make your Redux code base tinier and simpler to maintain

CircleCI Coverage Status NPM Version npm bundle size Greenkeeper badge

Migrating

Hey ! If you come from an early version of k-redux-factory and want to upgrade, you can read this migration guide 💎

Contents

Purpose

k-redux-factory creates generic reducers, actions and selectors in two lines.

import { keyValue } from 'k-redux-factory'
export default keyValue({ path: 'api', name: 'todos' })

That's it, you just exported the reducer function and now you can register it through combinerReducer in Redux.

In this example, we have a todos reducer, it has to be combined into state.api.todos.

The default key is id.

You can now use it to dispatch actions and select some datas from this reducer:

import myReducer from './myReducer'

// ...
// add a todo
dispatch(myReducer.add({ id: 1, title: 'Apply to some CFP', completed: false })

// ...
// select a todo
myReducer.get(1)(getState())

One more thing, this lib handle state immutability for you !

Click right here to see the full API.

Why

We like to write Redux code as simple as possible and use its middlewares to handle real world problems. From this point of view, our Redux code base is simpler : it's like a key/value store. But one drawback is the amount of duplicated code, each resource has its own reducers, actions and selectors.

We created this lightweight library, a factory of reducers, actions and selectors, to avoid inconsistency and painful maintainability from our growing Redux code base.

Installation

  • yarn add k-redux-factory
  • npm i k-redux-factory

Documentation

factory

You need to use the factory to get a new set of reducer/actions/selectors :

// modular factory
import { factory } from 'k-redux-factory'

// or - prebuild simple factory
import { simple } from 'k-redux-factory'

// or - prebuild simpleObject factory (DEPRECATED)
import { simpleObject } from 'k-redux-factory'

// or - prebuild keyValue factory
import { keyValue } from 'k-redux-factory'

There are multiple factories signatures, take you preferred between :

  • factory(middlewares)(options) : this is the root factory, with middlewares
  • factory(options) : this is the root factory, without middlewares
  • simple(middlewares)(options) : this is a simple factory with middlewares
  • simple(options) : this is a simple factory without middlewares
  • DEPRECATED simpleObject(middlewares)(options) : this is a simpleObject factory with middlewares
  • DEPRECATED simpleObject(options) : this is a simpleObject factory without middlewares
  • keyValue(middlewares)(options) : this is a keyValue factory with middlewares
  • keyValue(options) : this is a keyValue factory without middlewares

Parameters are :

  • middlewares (optional), contain an object with pre and post fields. Both are an array of middlewares to apply before and after the core middleware
  • options (mandatory), either a string representating the reducer name, either an object with these fields :
    • key (exists only for the keyValue type -optional-), the field used to identify your objects (id is the default value)
    • path (optional), where the reducer will be combined via combineReducer
      • if empty, the reducer will be register at the root level of the redux state
      • you can use dot notation, like api.raw: your reducer will be combined into state.api.raw.<your_reducer>
    • name (mandatory), the reducer name (for instance: todos)
      • it's used to generate actions types
      • it's used to retrieve informations from selectors
    • prefix (optional) is added to actions to avoid some collisions when there are two reducers with the same name in two distincts paths
    • type (optional) can be keyValue or simple.<type> (default is keyValue)
    • defaultData (optional), set the default data value, used by reset action and for initialisation (default is an empty object {} for simple.object and default hashmap model for keyValue - see keyValue types section)

Example:

  • this reducer will use id as key field
  • it's combined into state.api.raw
  • it's name is todos
  • have default data
import { factory } from 'k-redux-factory'

export default factory({ path: 'api.raw', name: 'todos' })

Data will be stored into state.api.raw.todos.

Types

Types are :

  • keyValue : your state is a hashmap, useful to bind your API to Redux with the following redux state model :
{
  data: [
    [<key1>, <instance1>],
    [<key2>, <instance2>],
  ],
  initialized: true,
}
  • simple : your state is directly your <instance>. This implies that you can not set undefined.
  • DEPRECATED simpleObject : your state is directly your <instance>. This implies that you can not set undefined.

Default type is keyValue.

reducer

The previous factory returns a function which is a reducer. You just have to combine it like any other reducer :

import { createStore, combineReducers, compose, applyMiddleware } from 'redux'

// import your reducer
// (created by k-redux-factory)
import todos from './myTodosReducer'

// create your Redux store as usual
const store = createStore(
  combineReducers({
    // [other reducer]
    api: combineReducers({
      // [other reducer]
      raw: combineReducers({
        // import your reducer into api.raw
        // since we configured this path
        todos,
      }),
      // [other reducer]
    }),
    // [other reducer]
  }),
  /* your Redux middlewares */
)

export default store

Exemple keyValue with default state

import { keyValue } from 'k-redux-factory'

const defaultData = [
  {
    id: 1,
    todo: 'write README.MD',
  },
  {
    id: 2,
    todo: 'watch rick and morty season three',
  },
]

export default keyValue({ defaultData })
{
  data: [
    [1, { id: 1, todo: 'write README.MD' }],
    [2, { id: 2, todo: 'watch rick and morty season three' }],
  ],
  initialized: true,
}

actions

The factory returns a function (this is the reducer) that also contains actions and selectors as fields. Some generic actions are available. By now, it's not possible to add custom ones.

To see them go to TYPES.md.

Example, we set todos to our typed keyValue reducer:

// import your reducer
// (created by k-redux-factory)
import todos from './myTodosReducer'

// dispatch can be given by one of your middleware (redux-thunk, redux-saga, etc)
// or it can be given by react-redux for example (mapDispatchToProps)
dispatch(
  // set todos
  todos.set([
    {
      id: '1', // we set 'id' as key in the factory
      visible: true,
      label: 'My first todo',
    },
    {
      id: '2',
      visible: false,
      label: 'This todo is done',
    },
  ])
)

You can also retrieve action name like this : todos.SET

selectors

The factory returns a function (this is the reducer) that also contains actions and selectors as fields. Some generic selectors are available. By now, it's not possible to add custom ones.

To see them go to TYPES.md.

Example, we retrieve the todo with id 1:

// import your reducer
// (created by k-redux-factory)
import todos from './myTodosReducer'

// state can be given by one of your middleware (redux-thunk, redux-saga, etc)
// or it can be given by react-redux for example (mapStateToProps)
todos.get('1')(state)

helpers

signature description comment
mapAction(<mapper(action)>) create middleware and map only redux action mapper(action) is mandatory
mapState(<regex>)(<mapper(state)>) create middleware and map the state of the corresponding redux actions type by the regex
reducer(<yourReducer(action, state)>) create a middleware from a standard redux reducer
mapPayload(<regex>)(<mapper(payload)>) create middleware and map the payload of the corresponding redux actions type by the regex

Example, we create a middleware but we modify only the action :

import { factory } from 'k-redux-factory'
// import your helpers
import { mapAction } from 'k-redux-factory/helpers'

// define a function to map action
const mapper = action => ({ ...action, type: `SET_${action.type}` })
// create your reducer and transform the type of action before core middleware
export default factory({ pre: [mapAction(mapper)] })({ path: 'api.raw', name: 'todos' })

Example, we create a middleware but we modify only the state :

import { factory } from 'k-redux-factory'
// import your helpers
import { mapState } from 'k-redux-factory/helpers'

// define a function to change state
const mapper = state => ({...state, todos: 'TODO_CHANGED'})
// create your reducer and transform the state before core middleware
export default factory({ pre: [mapState(/SET>TODOS/)(mapper)] })({ path: 'api.raw', name: 'todos' })

Example, we create a middleware but we modify action and state :

import { factory } from 'k-redux-factory'
// import your helpers
import { reducer } from 'k-redux-factory/helpers'

// define a function to map state depending on the action
const mapper = (action, state) => {
  switch (action.type) {
    case 'SET_TODOS': return { todos: 'TODOS_CHANGED' }
    case 'LOG_TODOS': console.log(state)
    default: return state
  }
}
// create your reducer and transform the action and state before core middleware
export default factory({ pre: [reducer(mapper)] })({ path: 'api.raw', name: 'todos' })

Example, we create a middleware but we modify only the payload :

import { factory } from 'k-redux-factory'
// import your helpers
import { mapPayload } from 'k-redux-factory/helpers'

// define a function to map payload
const mapper = payload => payload.map(p => ({ ...p, id: `ID_${p.id}` }))
// create your reducer and transform the payload before core middleware
export default factory({ pre: [mapPayload(/SET>TODOS/)(mapper)] })({ path: 'api.raw', name: 'todos' })

About uni rakun

uni rakun is created by two passionate french developers.

Do you want to contact them ? Go to their website

Guillaume CRESPEL Fabien JUIF
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].