useCompareEffect
/**
* useCompareEffect
* useEffect只是普通的浅比较,这里做了深比较
* useEffect的依赖是否相同,相同不触发
*/
import { useEffect, useRef } from 'react'
import { isEqual } from 'lodash'
export default function useCompareEffect(effect: React.EffectCallback, dependencies?: Object) {
function deepCompareDependencies(value: any) {
const ref = useRef()
if (!isEqual(value, ref.current)) {
ref.current = value
}
return ref.current
}
useEffect(effect, deepCompareDependencies(dependencies))
}
useDependencyEffect
/**
* 组件 componentDidMount 的时候不执行 useEffect 的方法
* 只有依赖变化的时候会执行
*/
import { useRef, useEffect } from 'react'
export default function useDependencyEffect(effect: React.EffectCallback, dependencies: any[]) {
const componentDidMount = useRef<boolean>(false)
useEffect(() => {
if (componentDidMount.current) {
effect()
}
}, dependencies)
/**
* 必须放在最底下
*/
useEffect(() => {
componentDidMount.current = true
}, [])
}
react不支持useState回调,建议采用useEffect,这里做了个useState的回调
/** useStateCallback setstate回调 */
export function useStateCallback<T>(initialState: T | (() => T)): [T, DispatchWithCallback<SetStateAction<T>>] {
const [state, _setState] = useState(initialState);
const callbackRef = useRef<Callback<T>>();
const isFirstCallbackCall = useRef<boolean>(true);
const setState = useCallback((setStateAction: SetStateAction<T>, callback?: Callback<T>): void => {
callbackRef.current = callback;
_setState(setStateAction);
}, []);
useEffect(() => {
if (isFirstCallbackCall.current) {
isFirstCallbackCall.current = false;
return;
}
callbackRef.current?.(state);
}, [state]);
return [state, setState];
}
// 使用: const [state, setstate] = useStateCallback()
基于ant4 prompt优化
/**
* 离开页面prompt
*/
import React, { SetStateAction, useMemo, useState, useCallback, useRef, useEffect, ReactNode } from 'react'
import { Prompt, useHistory } from 'umi';
import { Modal } from 'antd';
type Callback<T> = (value?: T) => void;
type DispatchWithCallback<T> = (value: T, callback?: Callback<T>) => void;
/** useStateCallback setstate回调 */
export function useStateCallback<T>(initialState: T | (() => T)): [T, DispatchWithCallback<SetStateAction<T>>] {
const [state, _setState] = useState(initialState);
const callbackRef = useRef<Callback<T>>();
const isFirstCallbackCall = useRef<boolean>(true);
const setState = useCallback((setStateAction: SetStateAction<T>, callback?: Callback<T>): void => {
callbackRef.current = callback;
_setState(setStateAction);
}, []);
useEffect(() => {
if (isFirstCallbackCall.current) {
isFirstCallbackCall.current = false;
return;
}
callbackRef.current?.(state);
}, [state]);
return [state, setState];
}
interface Iprops {
isPrompt: boolean
content?: string
}
export default function UsePrompt(props: Iprops) {
const [promptStatus, setpromptStatus] = useStateCallback(props.isPrompt)
const history = useHistory()
useEffect(() => {
setpromptStatus(props.isPrompt)
}, [props.isPrompt])
return (<>
<Prompt
when={promptStatus}
message={location => {
Modal.confirm({
title: '提示',
content: props.content || '确认离开吗?系统可能不会保存当前表单',
okText: '确认',
cancelText: '取消',
onOk: () => {
setpromptStatus(false, () => {
history.push(location.pathname)
return false
})
}
});
return false;
}}
/>
</>)
}