🚨 Shai-Hulud Strikes Again:834 Packages Compromised.Technical Analysis →
Socket
Book a DemoInstallSign in
Socket

@thebestco/store-manager

Package Overview
Dependencies
Maintainers
2
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@thebestco/store-manager

BestPrice state management library

latest
Source
npmnpm
Version
0.0.19
Version published
Weekly downloads
4
-20%
Maintainers
2
Weekly downloads
 
Created
Source

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

  • [productID]: {loaded: true, loading: false, errors: {}, pristine: {}, name: 'Tyler', lastname: 'Durden}
  • updateResource(id, 'name', 'Norton')
  • [productID]: {loaded: true, loading: false, errors: {}, pristine: {name: 'Tyler'}, name: 'Norton', lastname: 'Durden}
  • updateResource(id, 'name', 'Edward')
  • [productID]: {loaded: true, loading: false, errors: {}, pristine: {name: 'Tyler'}, name: 'Edward', lastname: 'Durden}
  • updateResource(id, 'name', 'Tyler')
  • [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;

Keywords

bestprice

FAQs

Package last updated on 21 Jan 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts