npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ramduck-redux

v2.0.0

Published

A duck toolbox for redux based on ramda :-*

Downloads

2

Readme

Ramduck Redux

Tired of creating reducers that aren't curried. Interested in partial application with Ramdajs ?

This little project brings the power of curry and composition (thanks to Ramda) into your redux project.

Previously

// reducer/user.js
export const INITIAL_STATE = {
  name: '',
  email: '',
};

// Actions types
export const CHANGE_NAME = 'change user name';
export const CHANGE_EMAIL = 'change user email';
export const CHANGE_USER = 'change user';

// Actions creator
export const changeName = name => ({ type: CHANGE_NAME, name });
export const changeEmail = email => ({ type: CHANGE_EMAIL, email });
export const changeUser = (name, email) => ({ type: CHANGE_USER, name, email });

// Reducer:
export default function (state = INITIAL_STATE, action) {
  switch(action.type) {
    case CHANGE_NAME:
      return {
        ...state,
        name: action.name,
      };
    case CHANGE_EMAIL:
      return  {
        ...state,
        email: action.email,
      };
    case CHANGE_USER:
      return {
        ...state,
        name: action.name,
        email: action.email,
      };
    default:
      return state;
  }
}

With Ramduck Redux

// reducer/user.js
import { action1, action2, createReducer, init, when, mergeAction } from 'ramduck-redux'
import { objOf, always, evolve, o, merge } from 'ramda'

export const initialState = {
  name: '',
  email: '',
};

// Actions creator
export const changeName = action1('change user name', name => { name });
// with obj of
export const changeEmail = action1('change user email', objOf('email'));
// with 2 arguments
export const changeUser = action2('change user', name => email => ({ name, email }))

// no need of action type, use your function as a string in order
// to retrieve the type:
// `${changeName}` === 'change user name'

// Reducer:
export default createReducer('user', [ // you must name it (handy with ramduck-react-redux)
  init(initialState),

  when(changeName, ({ name }) => state => ({
    ...state,
    name,
  })),

  // with evolve:
  when(changeEmail, ({ email }) => evolve({
    email: always(email),
  })),

  // with omit, merge and composition:
  when(changeUser, ({ name, email }) => state => ({
      ..state,
      name,
      email,
  })),

  // or with mergeAction (same behavior, it merge the action payload by removing
  // the type properties):
  // when(changeUser, mergeAction),
])


// In your main state file: reducer/index.js

import User from './user'
import { createRootReducer } from 'ramduck-redux'

// you can combine
// your reducers easily with:
const rootReducer = createRootReducer([ User ])

// your state will take the reducer name declare above and put it into a global
// state object of the shape:
// { user: <the user state> }

Installation

With npm:

npm i --save ramduck-redux

Or with yarn:

yarn add ramduck-redux

Usage

Actions

You can easily create curried action creator with the function action, action1, action2, action3, action4, actionN:

import { action, action1, action2, action3, action4 } from 'ramduck-redux'
import { objOf } from 'ramda'

// action with no parameter, only a type
const initialize = action('INITIALIZE');
// action with 1 parameter
const changeName = action1('CHANGE_NAME', objOf('name'))
// action with 2 parameter
const changeUser = action2('CHANGE_USER', name => email => ({ name, email }))
// same thing for action2, action3, action4 :)

// you can also create actions of N arguments with actionN
// const veryHugeAction = actionN(8, 'some type', a => b => c => e => f => g => h => i => ...)

// and then:
myAction() // { type: 'MY_TYPE' }
changeName('John') // { type: 'CHANGE_NAME', name: 'John' }
changeUser('John', '[email protected]') // { type: 'CHANGE_USER', name: 'John', email: '[email protected]' }

// action creators are curried:
const changeJohnEmail = changeUser('John'); // [Function]
const action = changeJohnEmail('[email protected]'); // { type: 'CHANGE_USER', name: 'John', email: '[email protected]' }

// no need of action types. You can access to the type be converting your
// action creator to string
`${changeUser}` === 'CHANGE_USER' // true

Reducer

You can create reducers much more easily with combine, init, when:

import { createReducer, createRootReducer, init, when } from 'ramduck-redux'

const simpleReducer = init({ name: 'John' });

simpleReducer(null, { type: 'some action' }); // { name: 'John' }
simpleReducer({ name: 'Jane' }, { type: 'some action' }); // { name: 'Jane' }

const changeNameReducer = when(
  'changeName',
  action => state => ({
    ...state,
    name: action.name,
  })
)

changeNameReducer({}, { type: 'changeName', name: 'john' }); // { name: 'john' }

// you can easily combine those methods to create much more complex
// reducers:
const reducer = createReducer('myReducerName', [
  init(myInitialState),

  when('SOME_TYPE', someTypeReducer),
  when('SOME_OTHER_TYPE', someOtherTypeReducer),
  when(['A', 'B'], somePluralActionReducer),
])

API Reference

data EmptyAction ::
  { type :: String
  }

data Action a ::
  { type :: String
  | a
  }

--| Actions helpers

action :: String -> () -> EmptyAction

actionN :: Number -> String -> (* -> a) -> * -> Action a

action1 :: String -> (a -> b) -> a -> Action b

action2 :: String -> (a -> b -> c) -> a -> b -> Action c

action3 :: String -> (a -> b -> c -> d) -> a -> b -> c -> Action d

action4 :: String -> (a -> b -> c -> d -> e) -> a -> b -> c -> d -> Action e

mergeAction :: Action a -> Object b -> Action { | a | b }


--| Reducers helpers

init :: a -> (Action b, a) -> a

whenAction :: String -> (Action a -> b -> b) -> (b, Action a) -> b

whenActions :: [String] -> (Action a -> b -> b) -> (b, Action a) -> b

when :: String|[String] -> (Action a -> b -> b) -> (b, Action a) -> b

createReducer :: String -> [((b -> Action a) -> b)] -> b -> Action a -> b

createRootReducer :: [((b -> Action a) -> b)] -> b -> Action a -> b