0

I'm trying to populate the UseState initial value to the values of my users first and last name according to the response I got 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 first initiate the state of both firstname and lastname to be an empty string.

In my form I then the default value currentUser?.user?.firstname and currentUser?.user?.lastname those values are set displayed correctly on the form input fields.

enter image description here

When I only change one of the fields the other remains an empty string because handleInput has not been called on that field, therefore never updating the input value to what the defaulValue is. When I then submit the form, the input that was never changed is overwritten to a blank string in the database.

Any way we can correct this behavior to that when currentUser is no longer null, we change the formData from a blank string to the correct value?

39fredy
  • 1,923
  • 2
  • 21
  • 40

2 Answers2

0

I figure out a way to do this, but I don't know if there is a better way of doing so.

Here is my solution:

    useEffect(() => {
        setFormData({
            firstname: (currentUser && currentUser?.firstname) || "",
            lastname: (currentUser && currentUser?.lastname) || "",
        })
    }, [currentUser]);
39fredy
  • 1,923
  • 2
  • 21
  • 40
0

Assuming the form input value is bound to the state value, a crude way to do this that will need a little refinement is to use a useEffect 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)
    }

Adding a loading state and only displaying the fields when the data is loaded will help. You might also want to move the state into a child component and initialise it when the data is loaded via props.

    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}
            />
        );
Stuart Nichols
  • 1,026
  • 1
  • 8
  • 11