我使用 react-modal 创建一个面板,一切似乎都运行良好。
但是一旦打开模态,我需要设置模态的最大值。我正在使用钩子,每当我尝试更新值时出错时,只能在 React 函数中调用钩子。我尝试了所有可能的方法,但无法解决问题。
期望: - 应调用 OnAfterOpen,并将最新的状态值传递给pos prop
。
这就是我尝试过的。
function useTop() {
const [top, setTop] = useState('100px');
useEffect(() => {
const handleResize = () => {
const hasRefClientHeight = contentRef.current && contentRef.current.clientHeight;
hasRefClientHeight < window.innerHeight ? setTop(`calc(100% - ${hasRefClientHeight}px)`) : setTop('100px');
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return top;
}
const Panel = () => {
// const newTop = useTop(); -- This is not working as modal content is not ready. Modal Content will be ready only if `onAfterOpen` triggers.
<Modal pos={useTop} onAfterOpen={useTop}><div ref={contentRef}>Test</div></Modal>
};
事实上,钩子的规则说:
https://reactjs.org/docs/hooks-rules.html
仅在顶层调用挂钩
不要在循环、条件或嵌套函数中调用 Hook。相反,始终在 React 函数的顶层使用 Hooks。通过遵循此规则,您可以确保每次渲染组件时都以相同的顺序调用 Hook。这就是允许 React 在多个 useState 和 useEffect 调用之间正确保留 Hooks 状态的原因。(如果您好奇,我们将在下面深入解释。
这对于 React 确保在每个渲染周期中以完全相同的顺序调用钩子是必要的。
似乎Modal
只有在挂载(打开(后才会调用useTop
,即它可能会跳过第一次渲染,违反了钩子规则并扰乱了顺序。
您可以尝试的一件事:
将useTop
钩的ref
传递并在里面处理。如果为 null,则不要执行任何操作,如果已经挂载,请附加侦听器并返回清理函数。
const Panel = () => {
const newTop = useTop(contentRef);
<Modal pos={newTop} onAfterOpen={null}><div ref={contentRef}>Test</div></Modal>
};
除了newTop
,您还可以返回一个触发newTop
重新计算的函数。类似于useState
的做法。并onAfterOpen
调用它.