form icon indicating copy to clipboard operation
form copied to clipboard

useStore select value with type "File" doesnt update

Open therour opened this issue 6 months ago • 2 comments

Describe the bug

using useStore with selector that returns a File instance never been updated. I assume it is because the shallow function used internally by useStore doesnt work as expected when comparing File instance.

Your minimal, reproducible example

Here in the markdown

Steps to reproduce

trying the shallow function

import { shallow } from 'tanstack/react-form';

const a = new File(["a"], "a");
const b = new File(["b"], "b");
console.log(shallow(a, b)); // always return true;

real use case

const field = useFieldContext<File | null>()
const value = useStore(field.store, (state) => state.value);
console.log('file name', value?.name) // once we have the value, the value is never changed again.

<input type="file" onChange={e => field.handleChange(e.target.files?.[0] ?? null)} />

Expected behavior

I expect the subscribed value should be updated whenever we update the File

How often does this bug happen?

None

Screenshots or Videos

No response

Platform

  • macOS
  • Chrome

TanStack Form adapter

react-form

TanStack Form version

1.9.0

TypeScript version

No response

Additional context

No response

therour avatar May 30 '25 05:05 therour

I just updated to 1.12.0 and it still doesnt work as expected.

the difference for reproducing it is that the shallow function is imported from @tanstack/react-store

therour avatar May 30 '25 05:05 therour

@therour Good catch! Could you repost this issue in the Tanstack Store repo?

LeCarbonator avatar May 30 '25 09:05 LeCarbonator

This seems to fix the problem for me temporarily. Might just help someone else.

// or undefined
field.handleChange(null)
setTimeout(() => {
  field.handleChange(file);
}, 0)

Seems only a transition from a primitive type to an object is handled properly, so setting it back to null first at least gets it to work until the bug is fixed.

Xetera avatar Jun 30 '25 21:06 Xetera

@Xetera thanks, but I actually managed to solve this by returning a record instead of file in the useStore

const { value } = useStore(field.store, (state) => {
  return { value: state.value }
})

looks like their shallow function that used by the tanstack/store can handle record better

therour avatar Jul 01 '25 15:07 therour