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

Fix warn when unsaved changes #6719

Merged
merged 5 commits into from
Nov 10, 2021
Merged

Conversation

djhi
Copy link
Contributor

@djhi djhi commented Oct 22, 2021

Closes #6678.

Tasks

  • Add unit tests for form subpaths

Description

The linked issue above was introduced by #6272 that fixed the issue ##6198 introduced by #6005.

However, all those workarounds were in fact necessary because of our implementation for warning users about potential data loss if they tried to leave a page with a form with modified fields. Indeed, the useWarnWhenUnsavedChanges was saving the form changes when the form was unmounted because a location change happened. If users cancelled the navigation, then the hook would renavigate to the previous location and reapplied the saved changes.

However, re-navigating to the previous location means we refetched the data, reapplied initial values for the loaded record (in case of edit) then reapplied the saved changes. All this lead to several workarounds to manage dirty states that introduced more problems.

This PR uses the history API to trigger the warning. This is better because it happens before the location change so we don't have to save changes and reapply them. This allows us to remove the workarounds.

@djhi djhi added the RFR Ready For Review label Oct 22, 2021
@djhi djhi added this to the 3.19.1 milestone Oct 22, 2021
@djhi djhi added WIP Work In Progress RFR Ready For Review and removed RFR Ready For Review WIP Work In Progress labels Oct 22, 2021
packages/ra-core/src/form/useInput.ts Show resolved Hide resolved
Object.keys(unsavedChanges).forEach(key =>
form.change(key, unsavedChanges[key])
const release = history.block(location => {
const isInsideForm = location.pathname.startsWith(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not true e.g. on a TabbedForm when the user arrives directly in tab 2 and navigates to tab 1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn, you're right. I'll have to figure out how to determine the form root path then

@djhi djhi added WIP Work In Progress and removed RFR Ready For Review labels Oct 25, 2021
@djhi djhi added RFR Ready For Review and removed WIP Work In Progress labels Oct 26, 2021
@fzaninotto
Copy link
Member

The isInsideForm test is still not good enough

const form = useForm();
const useWarnWhenUnsavedChanges = (
enable: boolean,
formRootPathname: string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a breaking change: you add a second compulsory parameter, which isn't set in e.g. SimpleForm

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's because FormWithRedirect set a default value when it's not provided

@djhi
Copy link
Contributor Author

djhi commented Oct 27, 2021

The isInsideForm test is still not good enough

Can you elaborate?

@djhi djhi requested a review from fzaninotto October 27, 2021 08:37
@fzaninotto fzaninotto merged commit e5158a3 into master Nov 10, 2021
@fzaninotto fzaninotto deleted the fix-warn-when-unsaved-changes branch November 10, 2021 16:48
@GTuooa
Copy link

GTuooa commented Apr 28, 2023

react-router v6 removed useHistory history.block is not work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
RFR Ready For Review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Input resets to defaultValue when empty
4 participants