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

create-async-slice

v1.2.9

Published

## Helper for creating async slices with redux toolkit to avoid boilerplates

Downloads

69

Readme

Create async slice

Helper for creating async slices with redux toolkit to avoid boilerplates

API

createAsyncSlice

Returns redux-toolit slice object with 4 actions:

  1. request - to dispatch request with payload for fetching data and set isProcessing: true
  2. success - to fulfill your store with success data from API
  3. error - to fulfill data with error from API response
  4. reset - to reset store's state

createAsyncMappingSlice

Stands for creating relations between async states or for making complicated async lists slices. Example: you're users are toggleable sections and when you toggle each section - you need to load company info for that certain user. So there's multiple loading companies for each opened user at the same time

Returns redux-toolit slice object with 4 actions:

  1. request - to dispatch request with payload for fetching data and set isProcessing: true Expects { id } as default. id is id of item in list which needs to get additional data e.g. company user id.
  2. success - to fulfill your store with success data from API. Expects { id, value } as default. value is your data you want put into your redux store
  3. error - to fulfill data with error from API response. Expects { id, error } as default.
  4. reset - to reset store's state. Expects { id } as default.

How does async slice's state look like?

// state.users
// createAsyncSlice:
{
  getUsers: {
    value: [{ name: 'Test user', id: 'user-id-1' }],
    isSuccess: true,
    isProcessing: false,
    error: null
  }
}

// createAsyncMappingSlice:
{
  getUserCompanies: {
    ['user-id-1']: {
      value: [{ name: 'Test Company', id: 'company-id-1' }],
      isSuccess: true,
      isProcessing: false,
      error: null
    }
  }
}

Usage

src/ducks/users/users.slices.ts

import { combineReducers } from 'redux';
import { createAsyncSlice } from 'create-async-slice';

export const getUsersSlice = createAsyncSlice<RequestPayload, SuccessPayload, ErrorPayload>({
  name: 'getUsers',
  selectAsyncState: (state) => state.users.getUsers // To get `getUsersSlice.selectors` work
});

/* RequestPayloadWithId, SuccessPayloadWithId, ErrorPayloadWithId:
these are optional since we always should pass an id of parent list by default
*/
export const getUserCompaniesSlice = createAsyncMappingSlice<RequestPayloadWithId, SuccessPayloadWithId, ErrorPayloadWithId>({
  name: 'getCompaiesByUserId',
  selectAsyncState: (state) => state.users.getCompaiesByUserId // To get `getUserCompaniesSlice.selectors` work
})

export const usersReducer = combineReducers({
  getUsers: getUsersSlice.reducer,
  getUserCompanies: getUserCompaniesSlice.reducer
});

src/ducks/users/users.sagas.ts


function* getUserCompaniesSaga({ payload }) {
  // id - companyId
  const { id } = payload;

  try {
    const { data } = yield call(usersApi.getUserCompanies, id);

    yield put(getUserCompaniesSlice.actions.success(data));
  } catch (e) {
    yield put(getUserCompaniesSlice.actions.error(e.message));
  }
}

function* getUsersSaga() {
  try {
    const { data } = yield call(usersApi.getUsers);

    yield put(getUsersSlice.actions.success(data));
  } catch (e) {
    yield put(getUsersSlice.actions.error(e.message));
  }
}

export function* usersSagas() {
  yield takeAll(getUsersSlice.actions.request, getUsersSaga);

  yield takeAll(getUserCompaniesSlice.actions.request, getUserCompaniesSaga);
}

src/store/reducers.ts

import { usersReducer } from '@ducks/users/users.slices';

export const reducers = {
  users: usersReducer,
};

src/components/Users.ts

import React, { useSelector, useDispatch, useEffect } from 'react';

import { getUsersSlice } from '@ducks/users/users.slice';
import { selectIsGetUsersProcessing, selectGetUsersData } from '@ducks/users/users.selectors';

export const Users = () => {
  const dispatch = useDispatch();

  const isProcessing = useSelector(getUsersSlice.selectors?.isProcessing);

  const usersData = useSelector(getUsersSlice.selectors?.value)

  useEffect(() => {
    dispatch(getUsersSlice.actions.request());
  }, []);

  return (
    <div>
      {usersData.map(user => (
        <User {...user}>
      ))}
    </div>
  )
}

src/components/User.ts

import React, { useSelector, useDispatch, useEffect } from 'react';

import { getUserCompaniesSlice } from '@ducks/users/users.slice';
import { selectIsGetUserCompanyProcessing, selectGetUserCompaniesByIdData } from '@ducks/users/users.selectors';

export const User = ({ id, name }) => {
  const dispatch = useDispatch();

  const isProcessing = useSelector(state => getUserCompaniesSlice.selectors?.isProcessing(state, { id }));

  const companiesData = useSelector(state => getUserCompaniesSlice.selectors?.value(state, { id }));

  useEffect(() => {
    dispatch(getUserCompaniesSlice.actions.request({ id }));
  }, [id]);

  return (
    <div>
      {companiesData.map(company => (
        <Company {...company}>
      ))}
    </div>
  )
}

API

Async Slice Options:

createAsyncSlice accepts all createSlice options and following:

| Option key | Description | Default Value | | ------------- | ------------- | ------------- | | selectAsyncState | (state) => AsyncState, optional. Redux selector which returns your async slice state (needed for using createAsyncSlice({ ... }).selectors). E.g: selectAsyncState: (state) => state.users.getUsers |


createAsyncMappingsSlice accepts all createAsyncSlice options and following: | Option key | Description | Default Value | | ------------- | ------------- | ------------- | | mappingsAmountLimit | number, optional. Limits max amount of items stored in slices state (to avoid memory leak) | undefined |