T
TanStack4w ago
genetic-orange

A complex form with multiple actions

Hi everyone, I wanted your advice on should I use Tanstack Form for my form functionality I have defined below. The reason I am asking is because right now I am not using any form management library and handling all the error state and everything manually, but I am not able to resolve the re-render problem with it so it is making my form very slow when there are a lot of rows. The requirement for the form are: - I am making a timesheet form where the user has to fill in hours and comments for each day. - The form should be a table - Each row the user selects there project, and then from Monday to Sunday they fill in their specific hours and comments. - Many actions can be performed like fetching data from some other apis to create new rows in the table automatically, saving the table and submitting the table. - First the project line needs to be submitted then for each day an api call needs to be made to save the days. - If there is an error saving the line then the error should be shown at the line level. If it is there when saving on a day it should be on day level. - Also during the submit action, I get an error from the server if any of the lines (of the table) are not submitted due to some reason. In that senario I need to show the user what is the error only for that row. - I am maintaining additional variable fetched, edited and deleted at the line and at the day level to make sure which api to call when actually update the data at the backend. - I am not maintain Local State at the input level as to sync with the actual main array I will have save it when the user unblurs from the input field. I have given the users a shortcut to save the table and I want it to happen even when the user has focused in a input box. - There is no validation happening on the client side all of it is being done on the server side.
6 Replies
genetic-orange
genetic-orangeOP4w ago
If something is unclear please tell me so that I can clarify the same. The main issue I am having right now is that when the lines in the table reaches around 14 the number of re-renders are so much that the form's responsiveness is hurt. Below is the data structure I am talking about
type Result = { type: "Success" } | { type: "None" } | { type: "Error", message: string }

// Add a type for weekday columns to improve type safety
export type WeekdayColumn =
| "Monday"
| "Tuesday"
| "Wednesday"
| "Thursday"
| "Friday"
| "Saturday"
| "Sunday";

// Helper type to ensure type safety when accessing weekday properties
// Add Result property to each weekday property

export type TimesheetTableDetail = {
Hours: number;
Comment: string;
fetched: boolean;
edited: boolean;
deleted: boolean;
Result: Result;
Date: Date;
};

type WeekdayTimesheetLine = {
[K in WeekdayColumn]: TimesheetTableDetail | undefined;
};

export interface TableLine extends WeekdayTimesheetLine {
LineNumber: number;
ProjectNumber: string | undefined;
TotalHours: number;
Comment: string;
Result: Result;
Status:
| "Draft"
| "Open"
| "Submitted"
| "Rejected"
| "Approved"
| "Pending;
selected: boolean;
fetched: boolean;
edited: boolean;
deleted: boolean;
}
type Result = { type: "Success" } | { type: "None" } | { type: "Error", message: string }

// Add a type for weekday columns to improve type safety
export type WeekdayColumn =
| "Monday"
| "Tuesday"
| "Wednesday"
| "Thursday"
| "Friday"
| "Saturday"
| "Sunday";

// Helper type to ensure type safety when accessing weekday properties
// Add Result property to each weekday property

export type TimesheetTableDetail = {
Hours: number;
Comment: string;
fetched: boolean;
edited: boolean;
deleted: boolean;
Result: Result;
Date: Date;
};

type WeekdayTimesheetLine = {
[K in WeekdayColumn]: TimesheetTableDetail | undefined;
};

export interface TableLine extends WeekdayTimesheetLine {
LineNumber: number;
ProjectNumber: string | undefined;
TotalHours: number;
Comment: string;
Result: Result;
Status:
| "Draft"
| "Open"
| "Submitted"
| "Rejected"
| "Approved"
| "Pending;
selected: boolean;
fetched: boolean;
edited: boolean;
deleted: boolean;
}
Here is the proper type definition of the Table Line. The Comment on Table line is used to sync the comments of each day.
correct-apricot
correct-apricot4w ago
I‘ll take a thorough look in the evening. For now, you can use discord‘s code block formatting for an easier time. ``` wrap your code in triple backticks like this ``` —>
wrap your code in triple backticks like this
wrap your code in triple backticks like this
genetic-orange
genetic-orangeOP4w ago
Thanks @Luca | LeCarbonator I added the proper type definations in the code block
correct-apricot
correct-apricot4w ago
alright, looks way more readable, cheers! Since you're still deciding, I'll copy each point and give some context / thoughts * I am making a timesheet form where the user has to fill in hours and comments for each day. The form should be a table * Each row the user selects there project, and then from Monday to Sunday they fill in their specific hours and comments. Do you have a table library already? You'll need access to the form hook inside the column, which can be troublesome with libraries like TanStack Table. We're working on a PR for it, but keep that in mind. The actual UI part of it is trivial, since we are headless. The structure is up to you. Fields are also allowed to be an object (so, in this case, one row of data as one field, since you probably don't need metadata for each cell) * Many actions can be performed like fetching data from some other apis to create new rows in the table automatically, saving the table and submitting the table. We have array helper functions that you can call, so in this case, pushFieldValue, swapFieldValue, removeFieldValue etc. * First the project line needs to be submitted then for each day an api call needs to be made to save the days. So one line is a form on its own? That can work too, but it sounds more complex. * If there is an error saving the line then the error should be shown at the line level. If it is there when saving on a day it should be on day level. You can specify that errors on form level should instead be moved to the field. This part should be no problem. * Also during the submit action, I get an error from the server if any of the lines (of the table) are not submitted due to some reason. In that senario I need to show the user what is the error only for that row. This does make it sound more like you want multiple forms, one per row. Submission and error handling would be way easier that way, but you'll need a layer above to manage "all" forms. We have reference code for that, so let me know if you'll go for that route. * I am maintaining additional variable fetched, edited and deleted at the line and at the day level to make sure which api to call when actually update the data at the backend. Form data can have fields that are unrelated to user-changeable ones. It's up to you to specify what fields you want to show. * I am not maintain Local State at the input level as to sync with the actual main array I will have save it when the user unblurs from the input field. I have given the users a shortcut to save the table and I want it to happen even when the user has focused in a input box. This one I'm not sure what you're referring to. Keep in mind that we don't have a public Persister API yet. It's planned, but it's not out yet. * There is no validation happening on the client side all of it is being done on the server side. As in you have validation, but it's server requests reporting errors? That's fine, of course you'll have API calls made when validating.
genetic-orange
genetic-orangeOP4w ago
- I am not using any table library for that table. - There is a single form only but it has TableLine which type I did provide above. The table is made using the table lines which are of the type TableLine. I have attached an image that shows the table. I am filling in project, project task then for each day I am filling in the hours and comment. The line data is stored in a different table and the day data is stored in a different table that has the reference to the line table. - On Save the data needs to be syncs with the server (a typical Update). When the user submits this table another workflow is run on the server and I get if it was successful or not for each line. So I need to update the error or success state of the line in that scenario. - I am using react so each of the input field is a different component. When I talk about local state I mean the state of that single input component. Since I am directly changing the values in the array that is making up the whole table here the whole table re-renders which causes a lag. A work around for this would have been having a local state of each input component which the user changes when they are changing the value in the input and then onBlur sync it with the main Array (it is a method that was shown in Tanstack Table for achieving similar functionality). The issue I have with the implementation is that the users when using the shortcut to submit the table data will not blur from the input. Then if I implement onBlur functionality myself I have the issue that I don't know after how much time does synchronous function to update the main array complete so that I can run the async function which will sync the data with the database.
No description
genetic-orange
genetic-orangeOP4w ago
Thanks for clarification on my other points. The help is much appreciated.

Did you find this page helpful?