PRESTIGE2930's avatar

How to send updated data with inertia useForm

This code is supposed to update the data prop on the use form and make the post request, but i sends the previous data.

I tried using useEffect but it cause the post request to be sent on page load beacuse of values being inserted into the props on page load.

Any ideas.

const Accessibles = ({ access, id }) => { const { post, data, setData, errors, processing } = useForm({ like: access.like, bookmark: access.bookmark, block: access.block, title: id, });

			const handleChange = (e, type) => {
			        // Check if the request is already processing
			        if (processing) {
			            return; // fixed typo "reurn" to "return"
			        }

			        // store updated values
			        setData((prev)=>({
			            ...prev,
			            [type]: e.target.checked
			        }))

			        // Make the post request
			        return post(route('accessibles', { id }), {
			            data: {
			                like: data.like,
			                bookmark: data.bookmark,
			                block: data.block,
			                title: id, // or `data.title` if you want to dynamically use it
			            },
			            onError: (error) => {
			                console.log(error); // Handle error appropriately
			            },
			            onSuccess: (response) => {
			                console.log(response); // Optionally handle the successful response
			            }
			        });

};

}

0 likes
4 replies
piljac1's avatar
piljac1
Best Answer
Level 28

data and setData are a result of useState under the hood. Setting a new value (using the related state setter method - setData in the current case) is not synchronous. It is queued and only updated at the next React render. If you want to use the updated value (object in your case), you need to assign it to a separate variable that you will interact with further down in your logic (instead of interacting directly with the data state).

const updatedData = {
	...data,
	[type]: e.target.checked
};

// store updated values
setData(updatedData);

// Make the post request
return post(route('accessibles', { id }), {
    data: {
        like: updatedData.like,
        bookmark: updatedData.bookmark,
        block: updatedData.block,
        title: id, // or `updatedData.title` if you want to dynamically use it
    },
    onError: (error) => {
        console.log(error); // Handle error appropriately
    },
    onSuccess: (response) => {
        console.log(response); // Optionally handle the successful response
    }
});

Additional info can be found here: https://react.dev/reference/react/useState#ive-updated-the-state-but-logging-gives-me-the-old-value

1 like
piljac1's avatar

But if you want to experiment with useEffect instead, but don't want it to trigger on initial render, you could try:

const isFirstRender = ref(true);

useEffect(() => {
    if (isFirstRender.current) {
        isFirstRender.current = false;

        return;
    }

    post(route('accessibles', { id }), {
        data: {
            like: data.like,
            bookmark: data.bookmark,
            block: data.block,
            title: id, // or `data.title` if you want to dynamically use it
        },
        onError: (error) => {
            console.log(error); // Handle error appropriately
        },
        onSuccess: (response) => {
            console.log(response); // Optionally handle the successful response
        }
    });
}, [data]);

Important note: Keyword is "experiment", because this is considered an anti-pattern. React docs specifically state that you should not be using effects to handle user events (in this case, you want to post when the change event is triggered, which is a user event).

See https://react.dev/learn/you-might-not-need-an-effect#how-to-remove-unnecessary-effects

1 like

Please or to participate in this conversation.