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

reduxsauce-fsa

v0.2.6

Published

Some aesthetic toppings for your Redux meal.

Downloads

1

Readme

npm module

What's The Story?

Provides a few tools for working with Redux-based codebases.

Currently includes:

  1. createReducer - declutter reducers for readability and testing
  2. createTypes - DRY define your types object from a string
  3. createActions - builds your Action Types and Action Creators at the same time

More coming soon...

createReducer

We're all familiar with the large switch statement and noise in our reducers, and because we all know this clutter, we can use createReducer to assume and clear it up! There's a few patterns I've learned (and was taught), but let's break down the parts of a reducer first:

  1. Determining the initial state.
  2. Running
  3. Knowing when to run.
  4. Injecting into the global state tree

Initial State

Every reducer I've written has a known and expected state. And it's always an object.

const INITIAL_STATE = { name: null, age: null }

If you're using seamless-immutable, this just get's wrapped. This is optional.

const INITIAL_STATE = Immutable({ name: null, age: null })

Running

A reducer is a function. It has 2 inbound parameters and returns the new state.

export const sayHello = (state = INITIAL_STATE, action) => {
  const { age, name } = action
  return { ...state, age, name }
}

Notice the export? That's only needed if you would like to write some tests for your reducer.

Knowing When To Run

In Redux, all reducers fire in response to any action. It's up to the reducer to determine if it should run in response. This is usually driven by a switch on action.type.

This works great until you start adding a bunch of code, so, I like to break out "routing" from "running" by registering reducers.

We can use a simple object registry to map action types to our reducer functions.

import Types from './actionTypes'

export const HANDLERS = {
  [Types.SAY_HELLO]: sayHello,
  [Types.SAY_GOODBYE]: sayGoodbye
}

The export is only needed for testing. It's optional.

Injecting Into The Global State Tree

I like to keep this in the root reducer. Since reducers can't access other reducers (lies -- it can, but it's complicated), my preference is to not have the reducer file have an opinion.

I like to move that decision upstream. Up to the root reducer where you use Redux's combineReducers().

So, that brings us back to reduxsauce. Here's how we handle exporting the reducer from our file:

export default createReducer(INITIAL_STATE, HANDLERS)

That's it.

Complete Example

Here's a quick full example in action.

// sampleReducer.js
import { createReducer } from 'reduxsauce'
import Types from './actionTypes'

// the initial state of this reducer
export const INITIAL_STATE = { error: false, goodies: null }

// the eagle has landed
export const success = (state = INITIAL_STATE, action) => {
  return { ...state, error: false, goodies: action.goodies }
}

// uh oh
export const failure = (state = INITIAL_STATE, action) => {
  return { ...state, error: true, goodies: null }
}

// map our action types to our reducer functions
export const HANDLERS = {
  [Types.GOODS_SUCCESS]: success,
  [Types.GOODS_FAILURE]: failure
}

export default createReducer(INITIAL_STATE, HANDLERS)

This becomes much more readable, testable, and manageable when you reducers start to grow in complexity or volume.

createTypes

Use createTypes() to create the object representing your action types. It's whitespace friendly.

// Types.js
import { createTypes } from 'reduxsauce'

export default createTypes(`
  LOGIN_REQUEST
  LOGIN_SUCCESS
  LOGIN_FAILURE

  CHANGE_PASSWORD_REQUEST
  CHANGE_PASSWORD_SUCCESS
  CHANGE_PASSWORD_FAILURE

  LOGOUT
`)

createActions

Use createActions() to build yourself an object which contains Types and Creators.

import { createActions } from 'reduxsauce'

const { Types, Creators } = createActions({
  loginRequest: ['username', 'password'],
  loginSuccess: ['username'],
  loginFailure: ['error'],
  logout: null,
  custom: (a, b) => ({ type: 'CUSTOM', total: a + b })
})

The keys of the object will become keys of the Creators. They will also become the keys of the Types after being converted to SCREAMING_SNAKE_CASE.

The values will control the flavour of the action creator. When null is passed, an action creator will be made that only has the type. For example:

Creators.logout() // { type: 'LOGOUT' }

By passing an array of items, these become the parameters of the creator and are attached to the action.

Creators.loginRequest('steve', 'secret') // { type: 'LOGIN_REQUEST', username: 'steve', password: 'secret' }

Changes

September 8, 2016 - 0.2.0

  • NEW adds createActions for building your types & action creators - @gantman & @skellock

May 17, 2016 - 0.1.0

  • NEW adds createTypes for clean type object creation - @skellock

May 17, 2016 - 0.0.3

  • DEL removes the useless createAction function - @skellock

May 17, 2016 - 0.0.2

  • FIX removes the babel node from package.json as it was breaking stuff upstream - @skellock

May 17, 2016 - 0.0.1