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

teedux

v2.1.6

Published

Typed redux-ducks

Downloads

70

Readme

Teedux

Build Status codecov contributions welcome

Disclaimer

  • This is a training project of mine - I scratched my own itch.
  • It's best consumed with TypeScript
  • It's not a silver bullet for all redux projects - just for the small ones ;)
  • It's very opinionated - I assume you use redux-thunk for side effects but there is a way of making it work with sagas too
  • I assume you know Ducks: Redux Reducer Bundles
  • I assume you use combineReducers

Motivation

Programmers using redux are often confused about how to structure their projects - where to put reducers, action creators and action types so that the navigation in the directory tree will not become a nightmare.

When I started I found Ducks: Redux Reducer Bundles and I still believe it is the simplest and most scalable solution out there (for the beginners).

Since I'm a TypeScript fan for a while I decided to take a shot at making it even more affordable with typing.

The problems I believe I solved are:

  • action types, action creators and reducer for any given aspect of the app are always separated somehow (even if they are in the same file you have to scroll a lot because of huge switch in the reducer)
  • writing sychronous action creators is a dumb job anyway
  • switch is not really the most bulletproof construct programmers know
  • you never know if the action types you defined are handled in reducer until you try to trigger them and see that it breaks
  • you never know if the action types are unique until you observe mutation of state in different branches of your state (where you do not expect them to be)
  • trying to make all that mess fully typed is a pain and it's very error prone

How those problems are solved:

  • you make a duck creator by passing initial state and prefix for all its action types to makeReduxDuck,
  • duck creator has only 2 methods: defineAction and getReducer
  • you do not have to write action creators - the only thing you need is to type the action payload, write action handler next to action type and give it some name (type) for easier debugging in Redux Dev Tools (all that using defineAction)
  • reducer is made automaticcaly out of handlers defined in defineAction calls and you get it using getReducer
  • when action arrives to given reducer it is directly passed to proper handler - no switch statement there (and we have type hints while writing that handler)

Installation

$ npm install teedux

or

$ yarn add teedux

Usage

import { makeReduxDuck } from 'teedux'

interface ITask {
  id: number
  title: string
  isDone: boolean
  createdAt: number
}

export interface IState {
  entities: ITask[]
}

const initialState: IState = {
  entities: []
}

// We make duck creator - every action type it handles
// will get `tasks` prefix since now.
const duck = makeReduxDuck('tasks', initialState)

export const addTask = duck.defineAction<{ title: string }>(
  // This is the suffix of action type 
  // (if not unique then you get an error on start of the app)
  'ADD_TASK', 
  // This is the action handler - first param: state, 
  // second param: action payload (action type is stripped so you do not have 
  // to think about it)
  ({ entities }, { title }) => ({
    entities: entities.concat({
      id: Date.now(),
      title,
      isDone: false,
      createdAt: Date.now()
    })
  })
)

export const setTasks = duck.defineAction<{ tasks: ITask[] }>(
  'SET_TASKS',
  (_, { tasks }) => ({
    entities: tasks
  })
)

export const toggleTaskDone = duck.defineAction<{ taskId: number }>(
  'TOGGLE_TASK_DONE',
  ({ entities }, { taskId }) => ({
    entities: entities.map(task => task.id !== taskId ? task : {
      ...task,
      isDone: !task.isDone
    })
  })
)

export const deleteTask = duck.defineAction<{ taskId: number }>(
  'DELETE_TASK',
  ({ entities }, { taskId }) => ({
    entities: entities.filter(task => task.id !== taskId)
  })
)

// That's how the reducer is made :)
export default duck.getReducer()

Contribution

I'm open for pull requests and feedback :)

You can find me on twitter: @cytrowski