diff --git a/src/components/UseImmutableTest.tsx b/src/components/UseImmutableTest.tsx index 9cf3425..6482d3f 100644 --- a/src/components/UseImmutableTest.tsx +++ b/src/components/UseImmutableTest.tsx @@ -2,17 +2,18 @@ import useImmutable from './useImmutable'; export default function UseImmutableTest() { const [imm] = useImmutable({ - x: 0, - y: 0, - z: { a: 1, b: 2, c: [0, 1, 2] }, + index: 0, + array: [{ count: 0 }, { count: 1 }, { count: 2 }], }); return (
{JSON.stringify(imm)}
- - + + + +
); } diff --git a/src/components/useImmutable.ts b/src/components/useImmutable.ts index a076c3d..ef2eb6f 100644 --- a/src/components/useImmutable.ts +++ b/src/components/useImmutable.ts @@ -66,27 +66,41 @@ function createEdgeForArray( value: PlainJSArray, setValue: Dispatch>> ) { + const edges = {} as Record; + + const set = (property: number, next: SetStateAction) => { + const current = value[property]; + const nextValue = typeof next === 'function' ? next(current) : next; + setValue((value) => [ + ...value.slice(0, property), + nextValue, + ...value.slice(property + 1), + ]); + }; + return new Proxy(value, { set: (target, property, value) => { if (typeof property === 'number') { - const set = (next: SetStateAction) => { - const v = typeof next === 'function' ? next(value) : next; - const edge = createEdge(v, set); - setValue((v) => [ - ...v.slice(0, property), - edge, - ...v.slice(property + 1), - ]); - }; - - set(value); + set(property, value); } return true; }, // @ts-expect-error get: (target, property: keyof PlainJSArray[]) => { - if (typeof property === 'number') { - return target[property]; + if ( + typeof property === 'number' || + (typeof property === 'string' && /\d+/.test(property)) + ) { + property = +property; + if (property in edges) { + return edges[property]; + } + + const item = target[property]; + const setThis = set.bind(null, property); + const edge = createEdge(item, setThis); + edges[property] = edge; + return edge; } else { // @ts-ignore if (inPlaceArrayOperations.includes(property)) { @@ -133,7 +147,5 @@ export default function useImmutable( const edge = useMemo(() => createEdge(value, setValue), [value]); - console.log('rerendered useImmutable'); - return [edge, setValue]; }