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

@thebestco/store-manager

v0.0.19

Published

BestPrice state management library

Downloads

25

Readme

BestPrice state management library

Getting started

Install

yarn add @thebestco/store-manager

Testing

yarn test

Documentation

makeResourceSubStore

Is going to be used for sub-stores like authentication, user

usage

All the parameters except the subStoreName are optional.

const userSubStore = makeResourceSubStore('user', {
  getInitialState,
  reducer,
  actions,
  sagas,
  actionTypes,
});

default initial state

{
  loading: true,
  loaded: false,
  processing: false,
  pristine: {},
  errors: {}
}

default actions

export const initialize = (values, { merge } = {}) => {};

export const update = (attr, value) => {};

export const updateBatch = values => {};

export const updateOnChange = ({ target }) => {};

export const reset = () => {};

export const startFetch = () => {};

export const doneFetch = payload => {};

export const failFetch = () => {};

export const startProcess = () => {};

export const doneProcess = () => {};

export const resetPristine = () => {};

export const resetPristineKey = attr => {};

makeCollectionSubStore

Should be used for sub-stores like products, images, etc. The sub store should contain pre-defined actions for both collection and collection resource handling.

usage

All the parameters except the subStoreName are optional.

const productsSubStore = makeCollectionSubStore('products', {
  getInitialState,
  reducer,
  actions,
  sagas,
  actionTypes,
  resourceOptions: {
    getInitialState,
  },
});

default initial state

{
  loading: true,
  loaded: false,
  processing: false,
  byId: {},
  ids: []
}

default resource initial state

{
  loading: true,
  loaded: false,
  processing: false,
  pristine: {},
  errors: {}
}

default actions

export const initialize = (values, { merge } = {}) => {};

export const update = (attr, value) => {};

export const updateBatch = values => {};

export const updateOnChange = ({ target }) => {};

export const reset = () => {};

export const startFetch = () => {};

export const doneFetch = payload => {};

export const failFetch = () => {};

export const startProcess = () => {};

export const doneProcess = () => {};

export const resetPristine = () => {};

export const resetPristineKey = attr => {};

// Resource

export const initializeResource = (id, values, { merge } = {}) => {};

export const updateResource = (id, attr, value) => {};

export const updateBatchResource = (id, values) => {};

export const updateOnChangeResource = (id, { target }) => {};

export const removeResource = id => {};

export const resetResource = id => {};

export const startFetchResource = id => {};

export const doneFetchResource = (id, payload) => {};

export const failFetchResource = id => {};

export const startProcessResource = id => {};

export const doneProcessResource = id => {};

export const resetPristineResource = id => {};

export const resetPristineKeyResource = (id, attr) => {};

makeStoreManager

const store = makeStoreManager([userSubStore, productSubStore]);

const {
  actions,
  actionTypes,
  sagas,
  subStoreNames,
  reducer,
  context,
  useDispatch,
  useSelector,
  useSubStoreSelector,
  useResourceSelector,
  useStore,
  addSubStores,
  removeSubStores,
  updateSagas,
  reset,
} = store;

actions.user.startProcess(); // {type: 'USER_START_PROCESS'}

actionTypes.user.startProcess; // 'USER_START_PROCESS'

const Foo = () => {
  const name = useSubStoreSelector('user', state => state.name);
  const dispatch = useDispatch();
  dispatch.user.stopProcess();
};

Code samples

Extending the sub stores

// products/provider/actionTypes.js
export default LAST_SEEN = 'PRODUCTS_LAST_SEEN';

// products/provider/actions.js
export const setLastSeen = id => ({
  type: actions.LAST_SEEN,
  id,
});

// products/provider/reducer.js
export const reducer = {
  [actions.LAST_SEEN]: (state, { id }) => ({ ...state, lastSeen: id }),
};

// products/provider/getInitialState.js
export default () => ({ lastSeen: null });

const subStore = makeCollectionSubStore('products', {
  getInitialState, // collection's initial state
  reducer,
  actions,
  resourceOptions: {
    getInitialState, // resource's initial state
    reducer, // resource's reducer
    actionTypes, // resource's action types
  },
});

Pristine state

The store tracks the fields that have changed since the last doneFetch/doneFetchResource. If there is a change a field, we should keep the pristine value in a pristine object.

  • The resetResource/reset actions should set the pristine values back to the state, and clear the pristine state
  • The initializeResource/initialize/doneFetchResource/doneFetch should reset the pristine state
  • The pristine updates should apply on the update/batchUpdate/updateResource/batchUpdateResource actions

Example

  1. [productID]: {loaded: true, loading: false, errors: {}, pristine: {}, name: 'Tyler', lastname: 'Durden}
  2. updateResource(id, 'name', 'Norton')
  3. [productID]: {loaded: true, loading: false, errors: {}, pristine: {name: 'Tyler'}, name: 'Norton', lastname: 'Durden}
  4. updateResource(id, 'name', 'Edward')
  5. [productID]: {loaded: true, loading: false, errors: {}, pristine: {name: 'Tyler'}, name: 'Edward', lastname: 'Durden}
  6. updateResource(id, 'name', 'Tyler')
  7. [productID]: {loaded: true, loading: false, errors: {}, pristine: {}, name: 'Tyler', lastname: 'Durden}

Create the root provider

const {
  actions,
  actionTypes,
  subStoreNames,
  sagas,
  reducer,
  context,
  useDispatch,
  useSelector,
  useSubStoreSelector,
  useResourceSelector,
  useStore,
  addSubStores,
  removeSubStores,
  updateSagas,
  reset,
} = makeStore([subStore]);

// re-export useDispatch, useSelector, useResourceSelector, context...

const makeReduxStore = () => {
  const sagaMiddleware = createSagaMiddleware();

  const store = createStore(
    reducer,
    {},
    composeWithDevTools({ name: "AppName" })(applyMiddleware(sagaMiddleware))
  );

  store.runSaga = sagaMiddleware.run;
  updateSagas(reduxStore.runSaga);

  return store;
};
const AppName = () => {
  const store = useMemo(() => makeReduxStore(), []);

  return (
    <Provider store={store} context={context}>
      <App {...props} />
    </Provider>
  );
};

Using the providers

import { useSelector, useDispatch } from '......provider';

const LastSeen = ({ id }) => {
  const loading = useSelector(state => state.products.loading);
  const dispatch = useDispatch();

  if (loading) {
    return <Loading />;
  }

  return <Button onClick={() => dispatch.products.setLastSeen(id)} />;
};

Add sub-stores dynamically

Add sub store and execute the sagas.

const subStores = [subStore1, subStore2, subStore3];

export default () => {
  const store = getStore();
  storeManager.addSubStores(store, store.runSaga, subStores);
};

Remove sub-stores dynamically

Remove given sub-stores.

// Substores is an array of instances.
const subStores = [subStore1, subStore2, subStore3];
// But can be also an array of strings of the substore names.
const subStoreNames = ['subStore1', 'subStore2', 'subStore3'];

export default () => {
  const store = getStore();
  storeManager.removeSubStores(store, subStores);

  // ... this also works
  storeManager.removeSubStores(store, subStoreNames);
};

Reset store

You can reset the store to it's initial state with the reset method.

// Suppose we have registered these stores dynamically in our app
const subStores = [subStore1, subStore2, subStore3];

// We can reset the store to it's initial state (will all the bootstrap sub-stores given)
export default () => {
  const store = getStore();
  storeManager.reset(store);
};

Dispatch

All substore actions

const dispatch = useDispatch();
dispatch.products.updateResource(id, 'rating', 5);

Substore actions

const dispatch = useDispatch('products');
dispatch.updateResource(id, 'rating', 5);

Selectors

useResourceSelector

Memoizes the selectors. Redux-store uses useSelector() with the default comparison strategy that is strict equality. The useResourceSelector most of the time selects a portion of the state. So, it works with shallowEqual strategy.

const rating = useResourceSelector('products', id, state => state.rating);

// does not rerender if `rating or loading` are not getting change
const {rating, state} = useResourceSelector('products', id, state => ({rating: state.rating, loading: state.loading});

useSubStoreSelector

Does not memoize, strict equality only

const ids = useSubStoreSelector('products', state => state.ids);

useSelector

Same as redux useSelector

const state = useSelector();
const loading = state.products.byId[id].loading;