Skip to content

Commit d02ca0a

Browse files
committed
Fix: resolve final lint warnings and memoize event handlers
- Wrap onChange handlers in useCallback to prevent hook effect churn\n- Remove unused screen import\n- Ensure all example components use stable references for form methods
1 parent 0ec506a commit d02ca0a

1 file changed

Lines changed: 22 additions & 12 deletions

File tree

apps/docs/src/remix-hook-form/use-on-form-value-change.stories.tsx

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { useOnFormValueChange } from '@lambdacurry/forms/remix-hook-form/hooks/u
44
import { Select } from '@lambdacurry/forms/remix-hook-form/select';
55
import { TextField } from '@lambdacurry/forms/remix-hook-form/text-field';
66
import type { Meta, StoryContext, StoryObj } from '@storybook/react-vite';
7-
import { expect, userEvent, within, screen, waitFor } from '@storybook/test';
8-
import { useState, useMemo } from 'react';
7+
import { expect, userEvent, within, waitFor } from '@storybook/test';
8+
import { useState, useMemo, useCallback } from 'react';
99
import { useFetcher } from 'react-router';
1010
import { useRemixForm, RemixFormProvider, getValidatedFormData } from 'remix-hook-form';
1111
import { z } from 'zod';
@@ -87,16 +87,21 @@ const CascadingDropdownExample = () => {
8787
});
8888

8989
// When country changes, update available states and reset state selection
90-
useOnFormValueChange({
91-
name: 'country',
92-
methods,
93-
onChange: (value) => {
90+
const handleCountryChange = useCallback(
91+
(value: string) => {
9492
const states = statesByCountry[value] || [];
9593
setAvailableStates(states);
9694
// Reset state when country changes
9795
methods.setValue('state', '');
9896
methods.setValue('city', '');
9997
},
98+
[methods],
99+
);
100+
101+
useOnFormValueChange({
102+
name: 'country',
103+
methods,
104+
onChange: handleCountryChange,
100105
});
101106

102107
// Don't render if methods is not ready
@@ -236,15 +241,15 @@ const AutoCalculationExample = () => {
236241
// which can disrupt interaction tests using Portals
237242
const methods = useMemo(() => rawMethods, [rawMethods]);
238243

239-
const calculateTotal = () => {
244+
const calculateTotal = useCallback(() => {
240245
const quantity = Number.parseFloat(methods.getValues('quantity') || '0');
241246
const pricePerUnit = Number.parseFloat(methods.getValues('pricePerUnit') || '0');
242247
const discount = Number.parseFloat(methods.getValues('discount') || '0');
243248

244249
const subtotal = quantity * pricePerUnit;
245250
const total = subtotal - subtotal * (discount / 100);
246251
methods.setValue('total', total.toFixed(2));
247-
};
252+
}, [methods]);
248253

249254
// Recalculate when quantity changes
250255
useOnFormValueChange({
@@ -409,10 +414,8 @@ const ConditionalFieldsExample = () => {
409414
const methods = useMemo(() => rawMethods, [rawMethods]);
410415

411416
// Show/hide fields based on delivery type
412-
useOnFormValueChange({
413-
name: 'deliveryType',
414-
methods,
415-
onChange: (value) => {
417+
const handleDeliveryTypeChange = useCallback(
418+
(value: string) => {
416419
setShowShipping(value === 'delivery');
417420
setShowPickup(value === 'pickup');
418421

@@ -423,6 +426,13 @@ const ConditionalFieldsExample = () => {
423426
methods.setValue('shippingAddress', '');
424427
}
425428
},
429+
[methods],
430+
);
431+
432+
useOnFormValueChange({
433+
name: 'deliveryType',
434+
methods,
435+
onChange: handleDeliveryTypeChange,
426436
});
427437

428438
// Don't render if methods is not ready

0 commit comments

Comments
 (0)