Skip to content

tanstack form subscription

Paulo Gomes da Cruz Junior edited this page Sep 25, 2026 · 1 revision

title: "Gotcha — TanStack Form useForm Does Not Re-render the Owning Component" type: fix-guide domain: frontend framework: react component: "FormulaConfigurationCreateForm" library: "@tanstack/react-form@1.33.5" tags: [tanstack-form, react, reactivity, state-management, gotcha] created: 2026-09-25 updated: 2026-09-25

Gotcha — TanStack Form useForm Does Not Re-render the Owning Component

Symptom

A component calls form.setFieldValue('startDate', '') from an event handler (any setFieldValue behaves the same). The form store updates, but the owning component does not re-render, so form.state.values.* reads in JSX and in derived calculations stay stale until some unrelated re-render happens.

Verified with @tanstack/react-form@1.33.5.

Root Cause

useForm does not subscribe the owning component to the form store. In node_modules/@tanstack/react-form/dist/esm/useForm.js, only the useSelector calls inside LocalSubscribe and the Field subscribe hooks re-render their components; the component that calls useForm is not among them. Direct reads of form.state.values never trigger a re-render on their own.

Fix

Subscribe to the specific values the component reads:

import { useForm, useSelector } from '@tanstack/react-form'; // useSelector re-exported from @tanstack/react-store

const startDate = useSelector(form.store, (state) => state.values.startDate);

useSelector(source, selector, options?) takes the form store as source (form.store is a { get, subscribe } object). Render from startDate, not from form.state.values.startDate.

Warning — Keep the Selector Narrow

An earlier attempt subscribed to the whole values object:

// Anti-pattern — every setFieldValue produces a new object identity
const values = useSelector(form.store, (state) => state.values);

That caused React error #185 (maximum update depth exceeded) in e2e. Every formula edit created a new formulas object through setFieldValue; the new identity re-rendered the component, a validation effect ran and called setFieldValue again, and the cycle repeated.

Select one primitive field per subscription (state.values.startDate). Add one useSelector per field the component needs.

Context

Discovered while fixing frontend/src/components/waste/Formula/FormulaConfigurationCreateForm/index.tsx on branch fix/1327-test-hardening-formula (PR #1351). The start-date review gate needed startDate to update reactively after the date input handler cleared an invalid value.

Related: Test Patterns — Formula Create Screen covers the same limitation from the test side.

Waste Plus Wiki

Home

Architecture

Codes

Decisions

Knowledge Base

Development

Changes

Clone this wiki locally