1.获取state的旧值 || 上一轮的state或props
公用hook
import { useRef, useEffect } from 'react';
export default function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
页面使用
const [currentMarker, setCurrentMarker] = useState({});
const prevMarkerRef = usePrevious(currentMarker);
原理:

2.实际演练
需求1:子页面更改全局状态,主页面监听全局状态--HomePage页面和Children2组件
需求2:主页面监听全局状态,调用子页面的方法,类似表单提交,需要注意是否能拿到最新的全局状态----HomePage页面和Children1组件
import React, {
useEffect,
useState,
forwardRef,
useImperativeHandle,
useRef,
} from 'react';
import { Button } from 'antd';
import { useSelector, useDispatch } from 'umi';
import usePrevious from './demo';
const Children1 = forwardRef((props, ref) => {
const datam = useSelector((state) => state.common.textData);
useImperativeHandle(ref, () => ({
update: async () => {
return await childrenClick1();
},
}));
const childrenClick1 = async () => {
console.log(datam, 'qwer');
};
return <Button></Button>;
});
const Children2 = () => {
const dispatch = useDispatch();
const childrenClick2 = () => {
dispatch({
type: 'common/saveData',
payload: '点击测试',
});
};
return <Button onClick={childrenClick2}>Children2</Button>;
};
const HomePage = () => {
const textRef = useRef(null);
const dispatch = useDispatch();
const datam = useSelector((state) => state.common.textData);
const [middleState, setMiddleState] = useState(undefined);
const prevMarkerRef = usePrevious(middleState);
useEffect(() => {
if (datam) {
console.log('first')
textRef.current.update();
}
setMiddleState(datam);
}, [datam]);
const handleClick = () => {
dispatch({
type: 'common/saveData',
payload: '主页面',
});
};
return (
<div>
<Children1 ref={textRef}></Children1>
<Children2></Children2>
<Button onClick={handleClick}>主页面</Button>
</div>
);
};
export default HomePage;
遇到问题:
错误的
// 当直接获取全局状态,使用时会拿到最新的值,不是上一个状态
const prevMarkerRef = usePrevious(datam)
正确的
const [middleState, setMiddleState] = useState(undefined);
const prevMarkerRef = usePrevious(middleState);
useEffect(() => {
setMiddleState(datam);
}, [datam]);
延伸
当需要获取上一个全局状态时,需要重新设置状态
useEffect(() => {
setMiddleState(datam);
}, [datam]);