|
2 | 2 | import { describe, expect, it, vi } from 'vitest' |
3 | 3 | import { render, waitFor, within } from '@testing-library/react' |
4 | 4 | import { userEvent } from '@testing-library/user-event' |
5 | | -import { StrictMode, useState } from 'react' |
| 5 | +import { StrictMode, useEffect, useState } from 'react' |
6 | 6 | import { useStore } from '@tanstack/react-store' |
7 | 7 | import { useForm } from '../src/index' |
8 | 8 | import { sleep } from './utils' |
@@ -1564,6 +1564,56 @@ describe('useField', () => { |
1564 | 1564 | expect(getByTestId('item-0')).toHaveTextContent('Alice') |
1565 | 1565 | }) |
1566 | 1566 |
|
| 1567 | + it('should rerender array field when mounted after async defaultValues resolve', async () => { |
| 1568 | + // Regression test for https://github.com/TanStack/form/issues/2201 |
| 1569 | + type Person = { name: string } |
| 1570 | + type FormData = { people: Person[] } |
| 1571 | + |
| 1572 | + function Comp() { |
| 1573 | + const [data, setData] = useState<FormData | null>(null) |
| 1574 | + |
| 1575 | + const form = useForm({ |
| 1576 | + defaultValues: data ?? { people: [] }, |
| 1577 | + }) |
| 1578 | + |
| 1579 | + useEffect(() => { |
| 1580 | + void Promise.resolve().then(() => { |
| 1581 | + setData({ people: [{ name: 'Alice' }, { name: 'Bob' }] }) |
| 1582 | + }) |
| 1583 | + }, []) |
| 1584 | + |
| 1585 | + if (!data) { |
| 1586 | + return <div data-testid="loading">loading</div> |
| 1587 | + } |
| 1588 | + |
| 1589 | + return ( |
| 1590 | + <form.Field name="people" mode="array"> |
| 1591 | + {(field) => { |
| 1592 | + const val = field.state.value ?? [] |
| 1593 | + return ( |
| 1594 | + <ol data-testid="list"> |
| 1595 | + {val.map((person, i) => ( |
| 1596 | + <li key={i} data-testid={`item-${i}`}> |
| 1597 | + {person.name} |
| 1598 | + </li> |
| 1599 | + ))} |
| 1600 | + </ol> |
| 1601 | + ) |
| 1602 | + }} |
| 1603 | + </form.Field> |
| 1604 | + ) |
| 1605 | + } |
| 1606 | + |
| 1607 | + const { getByTestId } = render(<Comp />) |
| 1608 | + expect(getByTestId('loading')).toBeInTheDocument() |
| 1609 | + |
| 1610 | + await waitFor(() => |
| 1611 | + expect(getByTestId('list').children).toHaveLength(2), |
| 1612 | + ) |
| 1613 | + expect(getByTestId('item-0')).toHaveTextContent('Alice') |
| 1614 | + expect(getByTestId('item-1')).toHaveTextContent('Bob') |
| 1615 | + }) |
| 1616 | + |
1567 | 1617 | it('should handle defaultValue without setstate-in-render error', async () => { |
1568 | 1618 | // Spy on console.error before rendering |
1569 | 1619 | const consoleErrorSpy = vi.spyOn(console, 'error') |
|
0 commit comments