Setting the UseState value with data received from trpc response

I am attempting to set the initial value of the UseState as the first and last names of my users based on the response received from the tRPC API.

    const { data: sessionData } = useSession();

    const { data: currentUser } = api.user.get.useQuery(
        undefined, // no input
        { enabled: sessionData?.user !== undefined }
    )

    const [formData, setFormData] = useState({
        firstname: "",
        lastname: "",
    });

    const updateUser = api.user.update.useMutation()

    const handleInput = (e: { target: { name: any; value: any; }; }) => {
        const fieldName = e.target.name;
        const fieldValue = e.target.value;

        setFormData((prevState) => ({
            ...prevState,
            [fieldName]: fieldValue
        }));
        console.log(formData)
    }


I initially set the state of both firstname and lastname to empty strings.

In the form, I then set the default value to currentUser?.user?.firstname and currentUser?.user?.lastname. These values are correctly displayed in the form input fields.

https://i.sstatic.net/nv611.png

When I only change one field, the other remains an empty string because handleInput has not been called on that field, thus not updating the input value to match the defaultValue. Subsequently, when I submit the form, the unchanged input is overwritten with a blank string in the database.

Is there a way to correct this behavior so that when currentUser is no longer null, we update the formData from a blank string to the correct value?

Answer №1

To ensure the form input value is synced with the state value, one approach is to utilize a useEffect hook on the currentUser value:

    const { data: sessionData } = useSession();

    const { data: currentUser } = api.user.get.useQuery(
        undefined, // no input
        { enabled: sessionData?.user !== undefined }
    )

    const [formData, setFormData] = useState({
        firstname: "",
        lastname: "",
    });

    useEffect(() => {
        if(currentUser)
            setFormData({
                firstName: currentUser.firstName,
                lastName: currentUser.lastName
            })
    ), [currentUser]);

    const updateUser = api.user.update.useMutation()

    const handleInput = (e: { target: { name: any; value: any; }; }) => {
        const fieldName = e.target.name;
        const fieldValue = e.target.value;

        setFormData((prevState) => ({
            ...prevState,
            [fieldName]: fieldValue
        }));
        console.log(formData)
    }

Incorporating a loading state and showing the fields only when the data has loaded can enhance user experience. Consider moving the state to a child component and initializing it based on props once the data has been fetched.

    const { data: sessionData } = useSession();

    const { data: currentUser, isLoading } = api.user.get.useQuery(
        undefined, // no input
        { enabled: sessionData?.user !== undefined }
    )

    if(isLoading)
        return (<div>Loading...</div>);
    else if(currentUser)
        return (
            <UserForm
                firstName={currentUser.firstName}
                lastName={currentUser.lastName}
            />
        );

Answer №2

I managed to find a solution for this, but I'm not sure if it's the most efficient way.

Below is how I approached it:

    useEffect(() => {
        setFormData({
            firstName: (loggedInUser && loggedInUser?.firstName) || "",
            lastName: (loggedInUser && loggedInUser?.lastName) || "",
        })
    }, [loggedInUser]);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating a contravariant function member in TypeScript?

I am facing a challenge with a class that contains a member which is a function taking an instance of the same class: class Super { public member: (x: Super) => void = function(){} use() {const f = this.member; f(this)} } However, I need the me ...

Angular 8: Master the art of HTML binding

I am facing an issue with displaying HTML content in Angular 8. **Note: The HTML template I receive from the database as JSON data needs to be displayed in Angular. I am fetching this template and saving it in a variable (e.g., plot), then passing that va ...

Error: The function _this. is not callable

I encountered a perplexing issue while attempting to call a service function within the subscribe() method of another service function call. The error message indicated a TypeError: TypeError: _this.fileloaderService.downloadFile is not a function I have ...

What is the reason behind the narrowing of the type by indexing into a mapped type?

This question is inspired by an amazing answer found here: My curiosity lies in why the indexing works in the mapped type trick. Let's illustrate with an example: type MyData = { a: { alpha: string; }; b: { beta: number; } } type ...

Error: Unable to locate 'v8' in NextJS when using Twin Macro

I am encountering the error message Module not found: Can't resolve 'v8' when using a package in Nextjs with TypeScript. If I use a .js file, everything works fine. However, when I switch to a .tsx file, it throws a Module Not found error. ...

Struggling to Retrieve Class-Declared Variable in Angular 2 HTML Template

In this scenario, I intended to use a service for retrieving data but encountered difficulties. As a result, I developed the functionality within my component instead. Despite successfully obtaining the 'photos' variable through an HTTP request, ...

Combine arrays of objects by comparing two attributes in Typescript

Suppose I have an array in TypeScript that looks like this: const array = [ { id_m: "123", period: "Q1/22", amount: 1000 }, { id_m: "123", period: "Q1/22", amount: 500 }, { id_m: "123&q ...

What is the method for activating a hook after a state change in a functional component?

I'm currently working on a custom pagination hook that interacts with an API to fetch data similar to React Query. The concept is straightforward. I aim to invoke this hook whenever a specific state (referred to as cursor) undergoes a change. Below i ...

What is the proper type declaration for incoming data from the backend in my TypeScript code when using axios?

In the TypeScript code snippet provided, the type for 'e' (used in the function for form submission) has been figured out. However, a question arises if this type declaration is correct. Additionally, in the catch block, the type "any" is used fo ...

Tips for integrating Material-Ui Autocomplete with Formik's Field component to create Multi-Select check boxes

Trying to integrate Formik's Field component with Material-Ui Autocomplete for multiple values that include checkboxes has been challenging. Whenever a value is selected from the dropdown list, the popup closes and needs to be reopened for the next se ...

List out the decorators

One query is bothering me - I am attempting to create my own version of Injectable and I need to determine if a specific decorator exists in my Class. Is there a way to list all decorators of a class? Let's take the example below. All I want to know i ...

Unlock the power of Angular Router to execute unique actions with each click

Exclude the route from the button actions: <div *ngFor="let data of allData" routerLink="/view-detail"> <div> <p>{{data.content}}</p> </div> <button>SaveData</button> <button>ApplyData</button> < ...

What steps should I take to enable a clock plugin for my Discord Bot using the Discordeno framework?

I recently attempted to develop a plugin for a Discord bot utilizing the Discordeno Library. The goal of this plugin was to automatically update the name of a Voice channel to display the local time on the computer every minute. However, I encountered an i ...

What is the TypeScript syntax for defining a component that does not require props to be passed when called?

Can you provide guidance on the correct type to specify for Component in order to compile this example without any type errors? import { memo } from "react"; import * as React from "react"; export function CustomComponent( props: ...

The output.library.type variable in WebPack is not defined

Currently, I am delving into WebPack with a shortcode. As part of my learning process, I am working on a code snippet that involves calculating the cube and square of a number, which are then supposed to be stored in a variable outlined in the webpack.conf ...

Is there a way to disable the useMutation function once it has successfully completed its

Greetings, I am facing an issue with the mutation below: export const useUserSearch = (data) => { return useMutation({ mutationKey: ["user-search", data], mutationFn: fetchUser, }); }; I have implemented it in my component as foll ...

Creating an array using the variables in a class

I am seeking a way to create an array in TypeScript that contains the values of existing class variables. For example: export class example{ static readonly a = 'aval'; static readonly b = 'bval'; static readonly c = 'cval&a ...

A TypeScript solution as an alternative to express-ws

For the past couple of days, I've been scouring the web in search of an alternative or assistance in creating a TypeScript Declaration for this task. Unfortunately, my efforts have proven fruitless so far. https://www.npmjs.com/package/express-ws Th ...

checking if the regex pattern matches every input

I am working with a regex named 'pattern' that is intended to allow only numbers as input. However, I'm noticing that both pattern.test("a") and pattern.test("1") are unexpectedly returning true. Can anyone explain why th ...

Selecting the appropriate color code based on a specified value

If the value of zoneTempDiff1 falls below 1.5, consider using temp: 1 color. If it exceeds 1.5, opt for temp: 2 color. The same logic applies to all different values such as -1, -2, 0, 1, 2, 3, 4, or 5, each corresponding to a specific color code. In cas ...