React context (hooks)没有更新所有引用



我试图实现一个自定义关闭回调模态。我使用了一个useState钩子来存储这个方法,并在已经定义的closemmodal()中执行它。我的问题是,当我试图从上下文中使用closemmodal时,回调会持续使用初始值,而不是更新后的值。

function ModalProvider({ children }) {
const [component, setComponent] = useState<React.ReactNode>(null);
const [styles, setStyles] = useState<React.CSSProperties>(null);
const [onClose, setOnClose] = useState<() => void>(null);
const openModal = ({
component,
containerStyles,
onClose,
}: OpenModalProps) => {
setComponent(component);
setStyles(containerStyles);
setOnClose(() => onClose);
};
const closeModal = () => {
onClose?.();
setComponent(null);
setStyles(null);
setOnClose(null);
};
return (
<ModalContext.Provider value={{ component, styles, openModal, closeModal }}>
{children}
</ModalContext.Provider>
);
}

这里我使用了两个点,按钮和自定义钩子useClickOutside。当我点击按钮时,它正常工作,但是当事件从钩子捕获时,发生的是模态关闭,但onClose没有执行,因为它是空的。

function Modal() {
const { component, styles, closeModal } = useContext(ModalContext);
const contentRef = useRef<HTMLDivElement>(null);
const [stopScrolling, continueScrolling] = useStopScrolling();
useClickOutside(contentRef, closeModal);
useEffect(() => {
if (!component) continueScrolling();
if (component) stopScrolling();
}, [component]);
if (!component) return <></>;
return (
<>
<S.ModalWrapper>
<section style={styles} ref={contentRef}>
<button onClick={closeModal}>x</button>
{component}
</section>
</S.ModalWrapper>
</>
);
}
function useClickOutside(ref, onClickOutside: () => void) {
const handleClickOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
onClickOutside();
}
};
useEffect(() => {
document.addEventListener("mousedown", handleClickOutside);
return () => {
window.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
}

我在其他应用程序点上使用此方法,也失败了,但我认为这可能足以发现问题。谢谢。

编辑

这是我调用模态

的方式
openModal({
component: <QuickView product={product} close={closeModal} />,
containerStyles: {
width: "80%",
maxWidth: "1000px",
height: "auto",
backgroundColor: "transparent",
},
onClose: () => {
const as = router.asPath;
router.push(as, as, { shallow: true });
},
});

由于在您的代码中有多个地方closeModal在闭包中被捕获而没有被声明为依赖项,因此它有可能在过时后被调用。

在这种情况下,更容易确保它永远不会有对onClose的过时引用,您可以通过使用useRef()而不是useState()来定义它:

const [component, setComponent] = useState<React.ReactNode>(null);
const [styles, setStyles] = useState<React.CSSProperties>(null);
// const [onClose, setOnClose] = useState<() => void>(null);
const onCloseRef = useRef<() => void>(null);
const openModal = ({
component,
containerStyles,
onClose,
}: OpenModalProps) => {
setComponent(component);
setStyles(containerStyles);
// setOnClose(() => onClose);
onCloseRef.current = onClose;
};
const closeModal = () => {
// onClose?.();
onCloseRef.current?.();
setComponent(null);
setStyles(null);
// setOnClose(null);
onCloseRef.current = null;
};

最新更新