T
TanStack5mo ago
broad-brown

Array of Objects with unique IDs

What's the way to go to handle
type Person = {
id: string;
firstName: string;
lastName: string;
}

type workers = { workers: Array<Person> }
type Person = {
id: string;
firstName: string;
lastName: string;
}

type workers = { workers: Array<Person> }
I would like to avoid to iterate over it just using the index (like shown here: https://tanstack.com/form/latest/docs/framework/react/guides/arrays) What I'd like to have would be something like this:
defaultValue: {
workers: {
"5": {
id: "5",
firstName: "Bob",
lastName: "Builder"
},
"6": {
id: "6",
firstName: "Clark",
lastName: "Kent"
}
}
}
defaultValue: {
workers: {
"5": {
id: "5",
firstName: "Bob",
lastName: "Builder"
},
"6": {
id: "6",
firstName: "Clark",
lastName: "Kent"
}
}
}
So I'd end up with something like this:
const workerId = "5"

<form.Field
name={`workers[`${workerId}`].firstName`}
// …
/>
const workerId = "5"

<form.Field
name={`workers[`${workerId}`].firstName`}
// …
/>
8 Replies
harsh-harlequin
harsh-harlequin5mo ago
how about restructuring to
type PersonId = string;

type FormValues = {
workers: Record<PersonId, Person>
}
type PersonId = string;

type FormValues = {
workers: Record<PersonId, Person>
}
then accessing with workers.id.firstName if it has to be dynamic list of objects, it might get tricky. I would either create an array of ids (that can also be changed to change the order of workers) or I would create a field of workers and extract the Object.values(field.state.value) people. Option 1:
type FormValues = {
workers: Record<PersonId, Person>;
workerOrdering: Array<PersonId>
}

<form.Field name="workerOrdering" mode="array">
{field => field.state.value.map(personId =>
<form.Field name={`workers.${personId}.firstName`}> </form.Field>
}
</form.Field>
type FormValues = {
workers: Record<PersonId, Person>;
workerOrdering: Array<PersonId>
}

<form.Field name="workerOrdering" mode="array">
{field => field.state.value.map(personId =>
<form.Field name={`workers.${personId}.firstName`}> </form.Field>
}
</form.Field>
Option 2:
type FormValues = {
workers: Record<PersonId, Person>;
}

<form.Field name="workers">
{field => Object.values(field.state.value)
.map(person => (
<form.Field name={`workers.${person.id}.firstName`}>
</form.Field>
))}
</form.Field>
type FormValues = {
workers: Record<PersonId, Person>;
}

<form.Field name="workers">
{field => Object.values(field.state.value)
.map(person => (
<form.Field name={`workers.${person.id}.firstName`}>
</form.Field>
))}
</form.Field>
I can really recommend option 1. I've had a good time with it, especially if you have a lot of nested data in workers. Reordering is really simple due to the primitive values
broad-brown
broad-brownOP5mo ago
I was hoping you'd be around and answer 🙂 Thanks Luca! I'll give it a try.
harsh-harlequin
harsh-harlequin5mo ago
you're free to ping me if you need a second pair of eyes :PepeThumbs: looking back, would option 2 work with the Map<string, Person> datatype? I never tried accessing deep values in a map with tanstack form I assume it doesn't work, but it just might
harsh-harlequin
harsh-harlequin5mo ago
it's cursed and it doesn't let you access stuff within. Who knew :OMEGALUL:
No description
broad-brown
broad-brownOP5mo ago
Works lovely! I put my Fields in a Tanstack-Table and can now reference them in a save way - thanks again! @Luca | LeCarbonator how are you handling the onChange-Event on the Input? It seems to work but I get a type error.
onChange={(e) => field.handleChange(e.target.value)}
onChange={(e) => field.handleChange(e.target.value)}
Argument of type 'string' is not assignable to parameter of type 'Updater<Person & string>'
https://stackblitz.com/edit/tanstack-form-yi8ij4tv?file=src%2Findex.tsx
harsh-harlequin
harsh-harlequin5mo ago
can‘t check the stackblitz right now, but is Person an object or a branded string here?
broad-brown
broad-brownOP5mo ago
type Person = {
name: string
}
type Person = {
name: string
}
harsh-harlequin
harsh-harlequin5mo ago
:Hmm: yeah I‘ll check the stackblitz later what a strange bug. Not sure why it happens it seems like subfields of workers.${id} have that issue of wrong inference

Did you find this page helpful?