|
1 | | -import { StrictMode, useEffect, useState } from 'react' |
| 1 | +import { StrictMode, useEffect, useLayoutEffect, useState } from 'react' |
2 | 2 | import { act, fireEvent, render, screen } from '@testing-library/react' |
3 | 3 | import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' |
4 | 4 | import { proxy, snapshot, useSnapshot } from 'valtio' |
@@ -399,6 +399,47 @@ describe('basic', () => { |
399 | 399 | expect(screen.getByText('count: 1')).toBeInTheDocument() |
400 | 400 | }) |
401 | 401 |
|
| 402 | + it('should not commit stale value for newly accessed keys on local rerender (regression in #1176)', async () => { |
| 403 | + const obj = proxy({ count: 0, anotherValue: 0 }) |
| 404 | + |
| 405 | + const commitFn = vi.fn() |
| 406 | + const Component = () => { |
| 407 | + const [showAnotherValue, setShowAnotherValue] = useState(false) |
| 408 | + const snap = useSnapshot(obj) |
| 409 | + const value = showAnotherValue ? snap.anotherValue : 'hidden' |
| 410 | + useLayoutEffect(() => { |
| 411 | + commitFn(value) |
| 412 | + }, [value]) |
| 413 | + return ( |
| 414 | + <> |
| 415 | + <div>count: {snap.count}</div> |
| 416 | + {showAnotherValue && <div>anotherValue: {snap.anotherValue}</div>} |
| 417 | + <button onClick={() => setShowAnotherValue(true)}> |
| 418 | + showAnotherValue |
| 419 | + </button> |
| 420 | + </> |
| 421 | + ) |
| 422 | + } |
| 423 | + |
| 424 | + render(<Component />) |
| 425 | + |
| 426 | + expect(screen.getByText('count: 0')).toBeInTheDocument() |
| 427 | + expect(screen.queryByText('anotherValue: 0')).not.toBeInTheDocument() |
| 428 | + expect(screen.queryByText('anotherValue: 1')).not.toBeInTheDocument() |
| 429 | + expect(commitFn).toBeCalledTimes(1) |
| 430 | + expect(commitFn).toHaveBeenNthCalledWith(1, 'hidden') |
| 431 | + |
| 432 | + obj.anotherValue += 1 |
| 433 | + |
| 434 | + await act(() => vi.advanceTimersByTimeAsync(0)) |
| 435 | + expect(commitFn).toBeCalledTimes(1) |
| 436 | + |
| 437 | + fireEvent.click(screen.getByText('showAnotherValue')) |
| 438 | + |
| 439 | + expect(screen.getByText('anotherValue: 1')).toBeInTheDocument() |
| 440 | + expect(commitFn.mock.calls.map(([value]) => value)).toEqual(['hidden', 1]) |
| 441 | + }) |
| 442 | + |
402 | 443 | it('counter with sync option', async () => { |
403 | 444 | const obj = proxy({ count: 0 }) |
404 | 445 |
|
|
0 commit comments