luisherranz / deepsignal

DeepSignal 🧶 - Preact signals, but using regular JavaScript objects

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unproxy an array

oravecz opened this issue · comments

In my code, I need to get the "raw" array from my deepsignal state, and I thought the RevertDeepSignal type might help me get there, but while I can get a clean array back - all of the 20,000 items in that array are Proxy objects. When I pass the array to a function that has no concept of signals, it treats the array as if it were empty.

Please take a look at the demonstrate() function below to see how I was hoping to get the raw array value back.

Note: in my particular case, I don't need the items in the arrays to be "deepsignaled", and those item's properties, and those item's properties... Just the array itself.

I'm not sure if that is an option?

interface WorkbookState {
  loadingState: WorkbookLoadingState;
  attributes: Attribute[];
  categories: Category[];
  hierarchies: Hierarchy[];
  hierarchy: Hierarchy | null;
  hierarchyNodes: HierarchyNode[];
  lrsSegments: Segment[];
  segments: Segment[];
  trees: ExplicitDataSource<PlanningTreeData> | null;
  workbook: Workbook | null;
}

const initialState: WorkbookState = {
  attributes: [],
  categories: [],
  hierarchy: null,
  hierarchyNodes: [],
  hierarchies: [],
  loadingState: WorkbookLoadingState.Initial,
  lrsSegments: [],
  segments: [],
  trees: null,
  workbook: null,
};

const store: WorkbookStore = {
  state: deepSignal<WorkbookState>(initialState),

  closeWorkbook,
  openWorkbook,
  setHierarchy,
};

const demonstrate = () => {
    const attributes: Attribute[] = Object.values<Attribute>(
      store.state.attributes as RevertDeepSignal<typeof store.state.attributes>,
    );

    // while the attributes array is properly types, attributes[n] are Proxy objects.

    // when I pass them to my AttributeLookup class, they do not work because the elements are Proxy objects
    const attributeLookup = new AttributeLookup(attributes);

    // my current work around is to do a deep copy of property to eliminate proxies
    const attributes: Attribute[] = toRaw(store.state.attributes);
}

function toRaw(val: any): any {
  if (val instanceof Array) return val.map((val) => toRaw(val));
  if (val instanceof Object)
    return Object.fromEntries(
      Object.entries(Object.assign({}, val)).map(([k, v]) => [k, toRaw(v)]),
    );
  return val;
}

RevertDeepSignal is only for the types. To get the raw value of the something from the store, you need to use peek(). The docs are here: https://github.com/luisherranz/deepsignal#peekstate-prop

const hugeArray = [
  /*...*/
];

const store = deepSignal({
  array: hugeArray,
});

const rawArray = peek(store, "array");

rawArray === hugeArray; // true

To stop something from being proxied, I'm thinking about a new shallow() API. There's a beta version published here if you want to try it out, but I haven't figured out the TypeScript part yet, so you may need to do manual casting for now:

Closing this now but feel free to reopen if you have more questions related to this topic.