@tanstack/react-form 0.16.1 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/tests/useField.test.tsx +115 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-form",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Powerful, type-safe forms for React.",
|
|
5
5
|
"author": "tannerlinsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@tanstack/react-store": "^0.3.1",
|
|
44
44
|
"decode-formdata": "^0.4.0",
|
|
45
45
|
"rehackt": "^0.0.3",
|
|
46
|
-
"@tanstack/form-core": "0.
|
|
46
|
+
"@tanstack/form-core": "0.18.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"react": "^17.0.0 || ^18.0.0"
|
|
@@ -608,6 +608,102 @@ describe('useField', () => {
|
|
|
608
608
|
expect(queryByText('A first name is required')).not.toBeInTheDocument()
|
|
609
609
|
})
|
|
610
610
|
|
|
611
|
+
it('should handle arrays with primitive values', async () => {
|
|
612
|
+
const fn = vi.fn()
|
|
613
|
+
function Comp() {
|
|
614
|
+
const form = useForm({
|
|
615
|
+
defaultValues: {
|
|
616
|
+
people: [] as Array<string>,
|
|
617
|
+
},
|
|
618
|
+
onSubmit: ({ value }) => fn(value),
|
|
619
|
+
})
|
|
620
|
+
|
|
621
|
+
return (
|
|
622
|
+
<div>
|
|
623
|
+
<form
|
|
624
|
+
onSubmit={(e) => {
|
|
625
|
+
e.preventDefault()
|
|
626
|
+
e.stopPropagation()
|
|
627
|
+
void form.handleSubmit()
|
|
628
|
+
}}
|
|
629
|
+
>
|
|
630
|
+
<form.Field name="people">
|
|
631
|
+
{(field) => {
|
|
632
|
+
return (
|
|
633
|
+
<div>
|
|
634
|
+
{field.state.value.map((_, i) => {
|
|
635
|
+
return (
|
|
636
|
+
<form.Field key={i} name={`people[${i}]`}>
|
|
637
|
+
{(subField) => {
|
|
638
|
+
return (
|
|
639
|
+
<div>
|
|
640
|
+
<label>
|
|
641
|
+
<div>Name for person {i}</div>
|
|
642
|
+
<input
|
|
643
|
+
value={subField.state.value}
|
|
644
|
+
onChange={(e) =>
|
|
645
|
+
subField.handleChange(e.target.value)
|
|
646
|
+
}
|
|
647
|
+
/>
|
|
648
|
+
</label>
|
|
649
|
+
<button
|
|
650
|
+
onClick={() => field.removeValue(i)}
|
|
651
|
+
type="button"
|
|
652
|
+
>
|
|
653
|
+
Remove person {i}
|
|
654
|
+
</button>
|
|
655
|
+
</div>
|
|
656
|
+
)
|
|
657
|
+
}}
|
|
658
|
+
</form.Field>
|
|
659
|
+
)
|
|
660
|
+
})}
|
|
661
|
+
<button onClick={() => field.pushValue('')} type="button">
|
|
662
|
+
Add person
|
|
663
|
+
</button>
|
|
664
|
+
</div>
|
|
665
|
+
)
|
|
666
|
+
}}
|
|
667
|
+
</form.Field>
|
|
668
|
+
<form.Subscribe
|
|
669
|
+
selector={(state) => [state.canSubmit, state.isSubmitting]}
|
|
670
|
+
children={([canSubmit, isSubmitting]) => (
|
|
671
|
+
<button type="submit" disabled={!canSubmit}>
|
|
672
|
+
{isSubmitting ? '...' : 'Submit'}
|
|
673
|
+
</button>
|
|
674
|
+
)}
|
|
675
|
+
/>
|
|
676
|
+
</form>
|
|
677
|
+
</div>
|
|
678
|
+
)
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
const { getByText, findByLabelText, queryByText, findByText } = render(
|
|
682
|
+
<Comp />,
|
|
683
|
+
)
|
|
684
|
+
|
|
685
|
+
expect(queryByText('Name for person 0')).not.toBeInTheDocument()
|
|
686
|
+
expect(queryByText('Name for person 1')).not.toBeInTheDocument()
|
|
687
|
+
await user.click(getByText('Add person'))
|
|
688
|
+
const input = await findByLabelText('Name for person 0')
|
|
689
|
+
expect(input).toBeInTheDocument()
|
|
690
|
+
await user.type(input, 'John')
|
|
691
|
+
|
|
692
|
+
await user.click(getByText('Add person'))
|
|
693
|
+
const input2 = await findByLabelText('Name for person 1')
|
|
694
|
+
expect(input).toBeInTheDocument()
|
|
695
|
+
await user.type(input2, 'Jack')
|
|
696
|
+
|
|
697
|
+
expect(queryByText('Name for person 0')).toBeInTheDocument()
|
|
698
|
+
expect(queryByText('Name for person 1')).toBeInTheDocument()
|
|
699
|
+
await user.click(getByText('Remove person 1'))
|
|
700
|
+
expect(queryByText('Name for person 0')).toBeInTheDocument()
|
|
701
|
+
expect(queryByText('Name for person 1')).not.toBeInTheDocument()
|
|
702
|
+
|
|
703
|
+
await user.click(await findByText('Submit'))
|
|
704
|
+
expect(fn).toHaveBeenCalledWith({ people: ['John'] })
|
|
705
|
+
})
|
|
706
|
+
|
|
611
707
|
it('should handle arrays with subvalues', async () => {
|
|
612
708
|
const fn = vi.fn()
|
|
613
709
|
function Comp() {
|
|
@@ -646,6 +742,12 @@ describe('useField', () => {
|
|
|
646
742
|
}
|
|
647
743
|
/>
|
|
648
744
|
</label>
|
|
745
|
+
<button
|
|
746
|
+
onClick={() => field.removeValue(i)}
|
|
747
|
+
type="button"
|
|
748
|
+
>
|
|
749
|
+
Remove person {i}
|
|
750
|
+
</button>
|
|
649
751
|
</div>
|
|
650
752
|
)
|
|
651
753
|
}}
|
|
@@ -680,10 +782,23 @@ describe('useField', () => {
|
|
|
680
782
|
)
|
|
681
783
|
|
|
682
784
|
expect(queryByText('Name for person 0')).not.toBeInTheDocument()
|
|
785
|
+
expect(queryByText('Name for person 1')).not.toBeInTheDocument()
|
|
683
786
|
await user.click(getByText('Add person'))
|
|
684
787
|
const input = await findByLabelText('Name for person 0')
|
|
685
788
|
expect(input).toBeInTheDocument()
|
|
686
789
|
await user.type(input, 'John')
|
|
790
|
+
|
|
791
|
+
await user.click(getByText('Add person'))
|
|
792
|
+
const input2 = await findByLabelText('Name for person 1')
|
|
793
|
+
expect(input).toBeInTheDocument()
|
|
794
|
+
await user.type(input2, 'Jack')
|
|
795
|
+
|
|
796
|
+
expect(queryByText('Name for person 0')).toBeInTheDocument()
|
|
797
|
+
expect(queryByText('Name for person 1')).toBeInTheDocument()
|
|
798
|
+
await user.click(getByText('Remove person 1'))
|
|
799
|
+
expect(queryByText('Name for person 0')).toBeInTheDocument()
|
|
800
|
+
expect(queryByText('Name for person 1')).not.toBeInTheDocument()
|
|
801
|
+
|
|
687
802
|
await user.click(await findByText('Submit'))
|
|
688
803
|
expect(fn).toHaveBeenCalledWith({ people: [{ name: 'John', age: 0 }] })
|
|
689
804
|
})
|