redux-auto icon indicating copy to clipboard operation
redux-auto copied to clipboard

async prop on root of store obj

Open codemeasandwich opened this issue 2 years ago • 2 comments

Would it be posable to add a "async" *the same as loading. On the root of the store as this is always an object. as would fix the case where parts of the store are not object/cant have the "loading" states injected into the prototype

codemeasandwich avatar Sep 22 '22 09:09 codemeasandwich

4 changes are need in 3 places

  1. create a new function
function combineReducersWithLoadingMeta(reducers, combineReducers){
  const s_a = combineReducers(reducers)
  return (state, action)=>{
      const __AUTO_loadingAsync_proto_ = state && state.loading ? Object.assign({},state.loading) : {}
      const __proto_ = {}
      Object.defineProperty(__proto_,"__AUTO_loadingAsync_proto_",{enumerable:false, writable: false, value: __AUTO_loadingAsync_proto_})
      const withProtoLoading = Object.create(__proto_)
      const actionWithInbedded_loadingAsync = Object.assign(withProtoLoading,action)
      const nextState = s_a(state, actionWithInbedded_loadingAsync)
      if(nextState !== state){
        return Object.assign(Object.create({loading:__AUTO_loadingAsync_proto_}),nextState)
      }
      return nextState
  }
}
  1. update the lib. Change:
    if (!(reducerName in reducers)) {
      reducers[reducerName] = function (data, action) {

        var avabileActions = lookup[reducerName];
        var actionFragments = action.type.split(".");

To:

    if (!(reducerName in reducers)) {
      reducers[reducerName] = function (data, action) {

      let loading_proto;
      if(action.__AUTO_loadingAsync_proto_){
        loading_proto = action.__AUTO_loadingAsync_proto_
        action = Object.assign({},action)
      }

        var avabileActions = lookup[reducerName];
        var actionFragments = action.type.split(".");

AND

Change:

        if (newAsyncVal || newState && isAsync[reducerName] && !newState.__proto__.async) {
        
          if (isObject(newState)) {

            var _newProto_ = {};
            Object.defineProperty(_newProto_, "async", { enumerable: false, writable: false, value: async });

And To:

if (loading_proto) {
            loading_proto[reducerName] = loading_proto[reducerName] || {}
}
        if (newAsyncVal || newState && isAsync[reducerName] && !newState.__proto__.async) {
        if (loading_proto) {
            loading_proto[reducerName] = async
        }
          if (isObject(newState)) {

            var _newProto_ = {};
            Object.defineProperty(_newProto_, "async", { enumerable: false, writable: false, value: async });

3 update the setup From:

const store = createStore(combineReducers(reducers), middleware );

To:

const store = createStore(combineReducersWithLoadingMeta(reducers,combineReducers), middleware );

codemeasandwich avatar Mar 06 '23 08:03 codemeasandwich

The above can be improved with

// combineReducers implementation
const combineReducersPoly = (reducers) => 
  const keys = Object.keys(reducers)
  return (state = {}, action) => {
    return keys.reduce((nextState, key) => {
      nextState[key] = reducers[key](state[key], action);
      return nextState;
    }, {});
  };
};

function combineReducersWithLoadingMeta(reducers, combineReducers){
  if( ! combineReducers){
    combineReducers = combineReducersPoly
  }
// ...

Then

const store = createStore(combineReducersWithLoadingMeta(reducers,combineReducers), middleware );

becomes

const store = createStore(combineReducersWithLoadingMeta(reducers), middleware );

codemeasandwich avatar Mar 06 '23 08:03 codemeasandwich