diff --git a/tests/basic.test.tsx b/tests/basic.test.tsx index 8d7599f9..dd2ce18b 100644 --- a/tests/basic.test.tsx +++ b/tests/basic.test.tsx @@ -173,118 +173,6 @@ it('no extra re-renders (render func calls in non strict mode)', async () => { expect(renderFn2).lastCalledWith(2) }) -it('no extra re-renders with nested useSnapshot (render func calls in non strict mode)', async () => { - const obj = proxy({ childCount: 0, parentCount: 0 }) - - const childRenderFn = vi.fn() - const Child = () => { - const snap = useSnapshot(obj) - childRenderFn(snap.childCount) - return ( - <> -
childCount: {snap.childCount}
- - - ) - } - - const parentRenderFn = vi.fn() - const Parent = () => { - const snap = useSnapshot(obj) - parentRenderFn(snap.parentCount) - return ( - <> -
parentCount: {snap.parentCount}
- - - - ) - } - - const { getByText } = render() - - await waitFor(() => { - getByText('childCount: 0') - getByText('parentCount: 0') - }) - - expect(childRenderFn).toBeCalledTimes(1) - expect(childRenderFn).lastCalledWith(0) - expect(parentRenderFn).toBeCalledTimes(1) - expect(parentRenderFn).lastCalledWith(0) - - obj.parentCount += 1 - - await waitFor(() => { - getByText('childCount: 0') - getByText('parentCount: 1') - }) - - expect(childRenderFn).toBeCalledTimes(2) - expect(childRenderFn).lastCalledWith(0) - expect(parentRenderFn).toBeCalledTimes(2) - expect(parentRenderFn).lastCalledWith(1) -}) - -it('no extra re-renders with child useSnapshot component (render func calls in non strict mode)', async () => { - const obj = proxy({ childCount: 0, anotherValue: 0 }) - - const childRenderFn = vi.fn() - const Child = () => { - const snap = useSnapshot(obj) - childRenderFn(snap.childCount) - return ( - <> -
childCount: {snap.childCount}
- - - ) - } - - const parentRenderFn = vi.fn() - const Parent = () => { - const [parentCount, setParentCount] = useState(0) - - parentRenderFn(parentCount) - - return ( - <> -
parentCount: {parentCount}
- - - - ) - } - - const { getByText } = render() - - await waitFor(() => { - getByText('childCount: 0') - getByText('parentCount: 0') - }) - - expect(childRenderFn).toBeCalledTimes(1) - expect(childRenderFn).lastCalledWith(0) - expect(parentRenderFn).toBeCalledTimes(1) - expect(parentRenderFn).lastCalledWith(0) - - obj.anotherValue += 1 - - fireEvent.click(getByText('parentButton')) - - await waitFor(() => { - getByText('childCount: 0') - getByText('parentCount: 1') - }) - - expect(childRenderFn).toBeCalledTimes(2) - expect(childRenderFn).lastCalledWith(0) - expect(parentRenderFn).toBeCalledTimes(2) - expect(parentRenderFn).lastCalledWith(1) -}) - it('object in object', async () => { const obj = proxy({ object: { count: 0 } }) diff --git a/tests/optimization.test.tsx b/tests/optimization.test.tsx new file mode 100644 index 00000000..6fc79f5d --- /dev/null +++ b/tests/optimization.test.tsx @@ -0,0 +1,116 @@ +import { useState } from 'react' +import { fireEvent, render, waitFor } from '@testing-library/react' +import { expect, it, vi } from 'vitest' +import { proxy, snapshot, useSnapshot } from 'valtio' + +it('regression: useSnapshot renders should not fail consistency check with extra render (nested useSnapshot)', async () => { + const obj = proxy({ childCount: 0, parentCount: 0 }) + + const childRenderFn = vi.fn() + const Child = () => { + const snap = useSnapshot(obj) + childRenderFn(snap.childCount) + return ( + <> +
childCount: {snap.childCount}
+ + + ) + } + + const parentRenderFn = vi.fn() + const Parent = () => { + const snap = useSnapshot(obj) + parentRenderFn(snap.parentCount) + return ( + <> +
parentCount: {snap.parentCount}
+ + + + ) + } + + const { getByText } = render() + + await waitFor(() => { + getByText('childCount: 0') + getByText('parentCount: 0') + }) + + expect(childRenderFn).toBeCalledTimes(1) + expect(childRenderFn).lastCalledWith(0) + expect(parentRenderFn).toBeCalledTimes(1) + expect(parentRenderFn).lastCalledWith(0) + + obj.parentCount += 1 + + await waitFor(() => { + getByText('childCount: 0') + getByText('parentCount: 1') + }) + + expect(childRenderFn).toBeCalledTimes(2) + expect(childRenderFn).lastCalledWith(0) + expect(parentRenderFn).toBeCalledTimes(2) + expect(parentRenderFn).lastCalledWith(1) +}) + +it('regression: useSnapshot renders should not fail consistency check with extra render', async () => { + const obj = proxy({ childCount: 0, anotherValue: 0 }) + + const childRenderFn = vi.fn() + const Child = () => { + const snap = useSnapshot(obj) + childRenderFn(snap.childCount) + return ( + <> +
childCount: {snap.childCount}
+ + + ) + } + + const parentRenderFn = vi.fn() + const Parent = () => { + const [parentCount, setParentCount] = useState(0) + + parentRenderFn(parentCount) + + return ( + <> +
parentCount: {parentCount}
+ + + + ) + } + + const { getByText } = render() + + await waitFor(() => { + getByText('childCount: 0') + getByText('parentCount: 0') + }) + + expect(childRenderFn).toBeCalledTimes(1) + expect(childRenderFn).lastCalledWith(0) + expect(parentRenderFn).toBeCalledTimes(1) + expect(parentRenderFn).lastCalledWith(0) + + obj.anotherValue += 1 + + fireEvent.click(getByText('parentButton')) + + await waitFor(() => { + getByText('childCount: 0') + getByText('parentCount: 1') + }) + + expect(childRenderFn).toBeCalledTimes(2) + expect(childRenderFn).lastCalledWith(0) + expect(parentRenderFn).toBeCalledTimes(2) + expect(parentRenderFn).lastCalledWith(1) +})