reactjs - 在React Router v6中,如何在离开页面/路由之前检查表单是否脏

标签 reactjs react-redux react-router material-ui

以下是我正在使用的软件包版本。

React version - 16.13.1
react-router-dom version - 6.0.0-beta.0
react-redux version 7.2.0
Material UI version 4.11.0
当用户试图离开当前页面时,检查表单isDirty(已更改)的最佳方法是什么?如果是isDirty的形式,我想提示“您确定要离开...吗?”。
我将从useEffect()中获取数据,并使用redux reducer来呈现UI。
我应该声明一个变量来保留原始获取的数据以进行脏检查吗?
这是我正在做的,但无法正常工作。
component.js
 useEffect(() => {
    props.fetchUserInfo();
 })
action.js
export function fetchUserInfo() {
 return (dispatch) => {
     dispatch({type: USER_INITIALSTATE, {Name: 'abc', Age: 20}} 
     )
 }
}
userReducer.js
const initialState = {
  processing: false,
  success: false,
  fail: false,
  Profile: {}
}
let oriState;
let State;
const UserReducer = (state = initialState, action) => {
  if (action.type === USER_INITIALSTATE) {
    oriState = {Profile: action.data};
    State = {...state, Profile: action.data};
    return {...state, Profile: action.data};
  } else if (action.type === OTHERS_ACTION) {
     //update field change
     return {...state, xxx}
  }
}
export const userIsDirty = state => {
  if (oriState && State) {
    return JSON.stringify(oriState.Profile) !== JSON.stringify(State.Profile);
  }
  return false;
};
export default UserReducer;
因此,在我的组件中,我调用userIsDirty返回isDirty bool 值,但是我尚未弄清如何捕获离开页事件并将其用作触发进行脏表单检查的触发器。
那么如何检测离开当前页面呢?我在useEffect return(component umount)上尝试过一些方法,但是 Prop 没有获得更新的INITIALSTATE状态(意味着我将获得Profile:{}),因为它只运行一次,但是如果我添加useEffect可选数组参数,我会得到无限循环(也许我设置错了?)。
useEffect(() => {
    props.fetchUserInfo();
    return () => {
      console.log(props); //not getting initial state object
    };
  }, []);
我这样做正确吗?我错过了什么?是否有更好/正确的解决方案来实现我想要的?
更新
谢谢@gdh,useBlocker是我想要的。我正在用它弹出一个确认对话框。
我将分享我完整的codeandbox,我相信这可能对将来的某人有所帮助。
show confirmation dialog by using useBlocker

最佳答案

此答案使用路由器v6。

  • 您可以使用usePrompt
  • usePrompt会在您转到另一条路线时(即在坐骑时)显示确认模式/弹出窗口。
  • 当您尝试关闭浏览器时,带有消息的常规警报。它在内部处理beforeunload

  • usePrompt("Hello from usePrompt -- Are you sure you want to leave?", isBlocking);
    
  • 您可以使用useBlocker
  • useBlocker会在尝试导航时(即在卸载的
  • 上)简单地阻止用户
  • 当您尝试关闭浏览器时,带有消息的常规警报。它在内部处理beforeunload

  • useBlocker(
        () => "Hello from useBlocker -- are you sure you want to leave?",
        isBlocking
      );
    
    Demo for both 1 & 2
  • 您也可以使用beforeunload。但是,您必须执行自己的逻辑。 See an example here
  • 关于reactjs - 在React Router v6中,如何在离开页面/路由之前检查表单是否脏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62792342/

    相关文章:

    reactjs - 为什么react-redux将连接的组件包装在Memo中

    javascript - 如何在一个组件中显示一个或多个详细信息 - React Native?

    javascript - react 路由器中的链接未定义错误

    javascript - 将 redux-devtools 与 jspm/system.js/babel 结合使用

    node.js - React 服务端渲染时使用 process.env

    Reactjs——父、子——每个的状态处理架构

    reactjs - enzyme 、ReactTestUtils 和 React-testing-library 之间的区别

    javascript - 使用 Spread Operator 更改数组中的属性返回对象而不是数组

    reactjs - 使用react-router-dom时如何避免 'Function components cannot be given refs'?

    javascript - 如何使用对象而不是组件/函数从 react-router-dom 渲染 <Route/>