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

@mfbtech/rtk-modules

v1.0.0

Published

Utilities to help modularize and test redux toolkit slice elements

Downloads

5

Readme

rtk-modules

Library of helper utilities for splitting Redux case reducers, thunks, and selectors across multiple file modules. Particularly useful in conjunction with Redux Toolkit's createSlice and React Redux's useSelector

Rationale

Redux, and in particular Redux Toolkit, encourage breaking redux store's up into feature- specific "slices." In some code bases, it is desirable to further break up those slices into modules containing the feature-specific case reducers, selectors, and async thunks. This can reduce file size, make testing easier, and even allow for isolating individual redux slices in their own npm packages.

This library provides some helper functions to make this process easier while preserving the excellent type safety and type inferences provided by Redux Toolkit. It also provides some testing utilities to make testing these modularized files easier.

Helper Utilities

produceCaseReducer

A function to make it easier to create an object full of named case reducers thatcan be passed to the reducers property of createSlice's argument.

 const createCounterReducer = produceCaseReducer<CounterState>()

 export const counterReducers = {
   someReducer: createCounterReducer((state,action) => {
     // reducer logic here
   })
  }

 //in slice.ts
 createSlice({
   ...
   reducers: createCounterReducers
 })

produceThunkReducerInjector

A function to make it easier to create asyncThunk case reducers in the same file you make the asyncThunks themselves, but following the same builder pattern used by createSlice

 const createCounterThunkReducerInjector = produceThunkReducerInjector<CounterState>()

 export const injectReducers = createCounterThunkReducerInjector( builder => {
   builder.addCase(someAsyncThunk.fulfilled, (state, action) => {
     // case reducer code here
   })
 }

 //in slice.ts
 createSlice({
   ...
   extraReducers: build => injectReducers(build)
 })

produceRootSelectors

A function that can turn selectors and selector creators written against slice state into selectors and selector creators, respectively, that operate against root state.

const counterPlainSelectors = {
  aSelector: (state: CounterState) => {
    //select some state
  }
}

const counterSelectorCreators = {
  aSelectorCreator: (x: number) => (state: CounterState) => {
    //select some state
  }
}

export const counterSelectors = produceRootSelectors<RootState>()(
  counterSlice.name
)(counterPlainSelectors, counterSelectorCreators)

// in a component
const mySelection = useSelector(counterSelectors.aSelector)
const myOtherSelection = useSelector(counterSelectors.aSelector(4))

Testing Utilities

produceAsyncThunkTester

A function to make it easier to test async thunks using an actual store containing the relevant slice.

// creates a mock store containing just the slice and with state configured
// based on an injected initial state or a function that transforms the
// slices initial state
let testAsyncThunk = produceAsyncThunkTester(
  counterSlice,
  injectedStartingState
)

it("example test", async () => {
  // runs the passed in async thunk through the store and returns the result
  // and modified state
  const { result, state } = await testAsyncThunk(counterThunks.someAsyncThunk())

  expect(Object.keys(result)).toContain("expectedString")
  expect(state.someState.length).toBe(3)
})

produceMockState and produceStateSetter

Lightweight functional programming utilities to create mock state from an initial state using a set of transformer functions. produceStateSetter generates the transformer functions, and produceMockState composes them together and uses them to transform an initial state object.

const set = produceStateSetter<OrdersState>()

it("example test", () => {
  const mockState = createMockState([
    set("availableProducts", [Product.floppy, Product.fdd]),
    set("orderQueue", [
      {
        id: "asdf8",
        customerId: 3,
        productType: Product.floppy,
        datePlaced: "2021-03-24"
      },
      {
        id: "lc73s",
        customerId: 7,
        productType: Product.fdd,
        datePlaced: "2021-03-24"
      }
    ])
  ])(initialOrdersState)
  /// continue with act and assertions of test
})

Examples

See the example subdirectory in this repository for a working, commented example of a slice that uses all these utilities.


Copyright 2022 MFB Technologies, Inc. See LICENSE for terms of use