Skip to content

Instantly share code, notes, and snippets.

@bolencki13
Last active July 28, 2025 12:58
Show Gist options
  • Select an option

  • Save bolencki13/dcb863292fedfcad86de5f23c94c9be8 to your computer and use it in GitHub Desktop.

Select an option

Save bolencki13/dcb863292fedfcad86de5f23c94c9be8 to your computer and use it in GitHub Desktop.
Implement a Proxy on an object to allow assignment of values while masking setState/dispatch in react
import { useMemo, useReducer } from 'react';
const isProxy = Symbol('is_proxy');
function setNestedValue<T extends object>(obj: T, path: string, value: any): T {
const parts = path.split('.');
let current: any = obj;
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
const isLastPart = i === parts.length - 1;
const nextPart = parts[i + 1];
const nextPartIsIndex = nextPart !== undefined && /^\d+$/.test(nextPart);
if (isLastPart) {
// This is the final part of the path, set the value
if (Array.isArray(current) && /^\d+$/.test(part)) {
const index = parseInt(part, 10);
// Ensure array is long enough, fill with undefined if sparse
while (current.length <= index) {
current.push(undefined);
}
current[index] = value;
} else {
// Otherwise, set as a regular object property
current[part] = value;
}
} else {
// Not the last part, navigate or create the next level
if (typeof current[part] !== 'object' || current[part] === null) {
// If the current part does not exist, or is not an object/array,
// decide whether to create an array or an object for the next level.
current[part] = nextPartIsIndex ? [] : {};
} else if (nextPartIsIndex && !Array.isArray(current[part])) {
// Current[part] exists but is not an array, and the next part implies an array.
// We need to overwrite current[part] with an empty array.
// This is a type coercion/transformation.
// You might want to log a warning here depending on strictness.
// console.warn(`Path segment "${part}" is not an array, but next segment "${nextPart}" suggests an array. Overwriting with empty array.`);
current[part] = [];
}
// If nextPartIsIndex is false and current[part] is an array, we'll proceed
// (allowing properties on arrays, e.g., `arr.myProp`).
// If nextPartIsIndex is true and current[part] is already an array, we'll proceed.
// If nextPartIsIndex is false and current[part] is already an object, we'll proceed.
current = current[part];
}
}
return obj; // Return the modified object
}
function useDataset<S>(initialState: S | (() => S)): S;
function useDataset<S = undefined>(): S | undefined;
function useDataset<S>(defaultValue?: S) {
const [state, dispatch] = useReducer((_, payload) => {
return structuredClone(payload);
}, defaultValue);
const clone = useMemo(() => {
function getProxy<T extends Record<string, unknown>>(obj: T, parentPath?: string[]): T {
return new Proxy(obj, {
deleteProperty(_, prop) {
throw new Error(`Property [${prop.toString()}] cannot be deleted`);
},
get: function (target, prop, receiver) {
if (prop === isProxy) {
return true;
}
if (
typeof (target as any)[prop] === 'object' &&
(target as any)[prop] != undefined
) {
return getProxy(
(target as any)[prop] as any,
[parentPath, prop].filter(Boolean).map((v) => v?.toString()) as typeof parentPath
);
}
return Reflect.get(target, prop, receiver);
},
set(target, prop, value) {
(target as any)[prop] = value;
const next = structuredClone(state);
dispatch(setNestedValue(next as any, [...(parentPath ?? []), prop].filter(Boolean).join('.'), value));
return true;
},
});
}
if (!state) {
return state;
}
return getProxy(state);
}, [state, dispatch]);
return clone as S;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment