Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transform method in useForm hook doesn't work #1631

Closed
aviemet opened this issue Jul 31, 2023 · 17 comments
Closed

transform method in useForm hook doesn't work #1631

aviemet opened this issue Jul 31, 2023 · 17 comments
Labels
react Related to the react adapter

Comments

@aviemet
Copy link

aviemet commented Jul 31, 2023

Version:

  • @inertiajs/react version: 1.0.9

Describe the problem:

I'm re-reporting an issue which was closed in the recent reset of issues, the original is #1131

When using useForm from the React package, the transform method doesn't work. The method is defined in the body of the useForm component, and thus is re-initialized upon re-renders to be the original "placeholder" method.

The transform method needs to be memoized in some way. I submitted #1491 which I've tested and it addresses this issue. It stores the transform method in a ref so that when it's value is updated it persists through re-renders.

@aviemet aviemet added the react Related to the react adapter label Jul 31, 2023
@saeidalidadi
Copy link

saeidalidadi commented Aug 19, 2023

I fixed this using a ref hook.

const transformRef = useRef({} as any);
useEffect(() => {
       transformRef.current = (data: any) => {};
       transform(transformRef.current)
});

@qMaDMaNp
Copy link

v1.0.11 - the problem persists.
If no changes have been made to the form fields, the transform() method is ignored thus not being called. =(

@Zagoman
Copy link

Zagoman commented Nov 6, 2023

This problem still persists

@aviemet
Copy link
Author

aviemet commented Nov 6, 2023

Nearly 3 years and this very basic error still persists. It genuinely makes me fear for the longevity of this amazing project. Inertia is the glue that binds the frontend and backend together and is exactly how I want to build projects, I really hope this isn't a foretelling of an eventual death of the project.

For anyone who needs a quick drop-in, I've built out a replacement for useForm which fixes the transform bug, and also adds a few other features. Please feel free to use it, improve it, steal it, etc. Hopefully one day it won't be necessary.

@rossity
Copy link

rossity commented Nov 13, 2023

@reinink @jessarcher can we get a confirmation you are aware of this bug and that there is a PR open for it? I'm not sure why this bug has been ignored for years now. It's core functionality to one of the best features of this library.

#1718

@ThePlatinum
Copy link

Surprisingly, it was working fine for me until I made an update and it stopped working, I undid all the changes and it still not working.

@dac514
Copy link

dac514 commented Dec 28, 2023

I fixed this using a ref hook.

const transformRef = useRef({} as any);
useEffect(() => {
       transformRef.current = (data: any) => {};
       transform(transformRef.current)
});

Allo! Can anyone reading explain this code snippet for me?

I tried it, and variations thereof, all it did was clear all data on every submit. 😕

I've been looking into this for a few hours and here's a summary of what I think I understand so far:

  1. That code snippet above can allegedly work around problem.
  2. This PR looks similar to the code snippet but is deeper: Memoize transform to fix long standing useForm bug #1718
  3. This package could also work: https://github.com/aviemet/useInertiaForm

As much as option 3 is great, kudos to the dev!, for me, it would be most interesting to get option 1 working, a temporary patch as we faithfully await option 2 to be merged.

More hints for idea 1 please? Thanks.

@dac514
Copy link

dac514 commented Jan 8, 2024

Following up on using saeidalidadi's snippet. I got something working.

Before:

transform((data) => {
    // REPLACE ME: your transform routine goes here
    return data
});

After:

import { useRef, useEffect } from 'react';
// ...
const transformRef = useRef({} as any);
useEffect(() => {
       transformRef.current = (data: any) => {
           // REPLACE ME: your transform routine goes here
           return data
       };
       transform(transformRef.current)
}, [data]);

Then, add onChange={(e) => setData('REPLACE_ME', e.target.value)} in as many places as possible to trigger re-renders so that your routine gets reloaded if ever it were to be replaced by the original inertia.js placeholder code.

@NaungYeHtet
Copy link

NaungYeHtet commented Jan 28, 2024

Surprisingly, it was working fine for me until I made an update and it stopped working, I undid all the changes and it still not working.

Same here. First it is working perfectly fine until I make some modification to the code. But undo changes is not helping either.

One thing I noticed that it is working after the code has an error and fix it. But It is not working after refresh.

@threesil

This comment was marked as spam.

@hasan-almujtaba

This comment was marked as spam.

@derrickreimer
Copy link
Contributor

I've been looking into this one and believe I arrived at the crux of the confusion. The transform function is designed to be called in the body of the component, not inside a handler function. As long as you place it in the body, you should be good to go. To give a concrete example:

This works:

const Page = () => {
  const { post, transform } = useForm({});

  transform((data) => ({ ...data, foo: "bar" }));
  
  const handleSubmit = (e) => {
    e.preventDefault();
    post("/route");
  }

  // ...
}

This does not work:

const Page = () => {
  const { post, transform } = useForm({});
  
  const handleSubmit = (e) => {
    e.preventDefault();
    transform((data) => ({ ...data, foo: "bar" }));

    // A re-render gets triggered somewhere in `post`, 
    // which wipes out the `transform` call just made
    post("/route");
  }

  // ...
}

(Discussed here: #1491 (comment))

@andcl
Copy link

andcl commented Jun 27, 2024

Then, as pointed in #1491, I think it should be noted in the docs that transform is the only method of the useForm hook that must be called from the component body and not from inside any component's handler function. That would save much time to people trying to use it for the first time...

@driesvints
Copy link
Contributor

Thanks @andcl. Could you maybe attempt a PR to the docs?

@andcl
Copy link

andcl commented Jul 10, 2024

Done. inertiajs/inertiajs.com#348

@agustinzamar
Copy link

Even if the originally intended behavior of the transform method is to be used in the component's body, It will be much more useful if could be used like #1131. At least for me it feels hacky storing a value in a ref or somewhere else to be later used in the transform.

Maybe a solution like the one proposed here could also work.

Another posibility could be to merge the form state with the data provided in the submit method. I would make this have precedence over the current state so it can be overriden. Currently the data is ignored and only the form state is submitted.

form.post(route('my-route'), {
  data: {foo: 'bar'} // Merge this with the current form state
})

@pedroborges
Copy link
Collaborator

This has been fixed by #1607.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
react Related to the react adapter
Projects
None yet
Development

No branches or pull requests