Dev*_*evb 10 reactjs react-router material-ui react-redux
以下是我正在使用的软件包版本。
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
Run Code Online (Sandbox Code Playgroud)
isDirty当用户试图离开当前页面时,如何/什么是检查表单(已更改)的最佳方法?如果表单isDirty.
我将从内部获取数据useEffect()并使用 redux reducer 来呈现 UI。
我应该声明一个变量来保留原始获取的数据以进行脏检查吗?
这就是我正在做的事情,但它无法正常工作。
组件.js
useEffect(() => {
props.fetchUserInfo();
})
Run Code Online (Sandbox Code Playgroud)
动作.js
export function fetchUserInfo() {
return (dispatch) => {
dispatch({type: USER_INITIALSTATE, {Name: 'abc', Age: 20}}
)
}
}
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
所以在我的组件中,我调用userIsDirty返回 isDirty 布尔值,但我还没有弄清楚如何捕获离开页面事件并将其用作触发器来进行脏表单检查。
那么如何检测离开当前页面呢?我在 useEffect return(component umount) 上尝试了一些东西,但是 props 没有得到更新的 INITIALSTATE 状态(意味着我会得到 Profile: {}),因为它只运行一次,但是如果我添加 useEffect 可选数组参数,我得到一个无限循环(也许我设置错了?)。
useEffect(() => {
props.fetchUserInfo();
return () => {
console.log(props); //not getting initial state object
};
}, []);
Run Code Online (Sandbox Code Playgroud)
我这样做是否正确?我错过了什么?有没有更好/正确的解决方案来实现我想要的?
谢谢@gdh,useBlocker是我想要的。我用它来弹出一个确认对话框。
我将分享我的完整代码和盒子,我相信这可能对将来的某人有所帮助。
gdh*_*gdh 15
此答案使用路由器 v6。
usePrompt("Hello from usePrompt -- Are you sure you want to leave?", isBlocking);
Run Code Online (Sandbox Code Playgroud)
useBlocker(
() => "Hello from useBlocker -- are you sure you want to leave?",
isBlocking
);
Run Code Online (Sandbox Code Playgroud)
acS*_*ter 10
只是为 React Router v6 用户添加一个额外的答案。
从 v6.0.0-beta 开始 - useBlocker 和 usePrompt 已被删除(稍后会添加回来)。
建议如果我们在 v6.0.2(撰写本文时的当前版本)中需要它们,我们应该使用现有代码作为示例。
因此,要将钩子添加回来,将是以下代码(在应用程序中的任何位置供使用):**我只复制了react-router-dom的代码 - 如果您使用的是本机,那么您需要检查上面的内容另一个usePrompt钩子的链接
/**
* These hooks re-implement the now removed useBlocker and usePrompt hooks in 'react-router-dom'.
* Thanks for the idea @piecyk https://github.com/remix-run/react-router/issues/8139#issuecomment-953816315
* Source: https://github.com/remix-run/react-router/commit/256cad70d3fd4500b1abcfea66f3ee622fb90874#diff-b60f1a2d4276b2a605c05e19816634111de2e8a4186fe9dd7de8e344b65ed4d3L344-L381
*/
import { useContext, useEffect, useCallback } from 'react';
import { UNSAFE_NavigationContext as NavigationContext } from 'react-router-dom';
/**
* Blocks all navigation attempts. This is useful for preventing the page from
* changing until some condition is met, like saving form data.
*
* @param blocker
* @param when
* @see https://reactrouter.com/api/useBlocker
*/
export function useBlocker( blocker, when = true ) {
const { navigator } = useContext( NavigationContext );
useEffect( () => {
if ( ! when ) return;
const unblock = navigator.block( ( tx ) => {
const autoUnblockingTx = {
...tx,
retry() {
// Automatically unblock the transition so it can play all the way
// through before retrying it. TODO: Figure out how to re-enable
// this block if the transition is cancelled for some reason.
unblock();
tx.retry();
},
};
blocker( autoUnblockingTx );
} );
return unblock;
}, [ navigator, blocker, when ] );
}
/**
* Prompts the user with an Alert before they leave the current screen.
*
* @param message
* @param when
*/
export function usePrompt( message, when = true ) {
const blocker = useCallback(
( tx ) => {
// eslint-disable-next-line no-alert
if ( window.confirm( message ) ) tx.retry();
},
[ message ]
);
useBlocker( blocker, when );
}Run Code Online (Sandbox Code Playgroud)
那么用法将是:
const MyComponent = () => {
const formIsDirty = true; // Condition to trigger the prompt.
usePrompt( 'Leave screen?', formIsDirty );
return (
<div>Hello world</div>
);
};Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5022 次 |
| 最近记录: |