模态组件在打开时呈现两次
Modal component renders Twice on open
我正在使用 react-spring 为基于 @reach/dialog 的模态框制作动画。 Modal 可以有任何 children。在 children 中,我正在根据一些道具获取一些数据。
问题是在打开模式时进行了两次提取调用。我认为这可能与我管理状态的方式有关,这导致 re-renders。
我试过在模态框内记忆 children 但没有用,所以我认为问题出在模态框组件之外。
这里有一些接近我的代码的东西以及它是如何工作的https://codesandbox.io/s/loving-liskov-1xouh
编辑:我已经知道,如果我删除 react-spring 动画,双重渲染不会发生,但我想尝试保持动画完好无损。
你觉得你能帮我找出错误在哪里吗? (也非常感谢一些关于钩子的良好实践的技巧)。
我查了一下,是因为Modal组件中的动画,当一个动画结束时渲染了两次,当我注释掉负责动画的fragment时,模态渲染了第二次,Modal只渲染了一次。
const Modal = ({ children, toggle, isOpen }) => {
// const transitions = useTransition(isOpen, null, {
// from: { opacity: 0 },
// enter: { opacity: 1 },
// leave: { opacity: 0 }
// });
console.log("render");
const AnimatedDialogOverlay = animated(DialogOverlay);
// return transitions.map(
// ({ item, key, props }) =>
// item && (
return (
<AnimatedDialogOverlay isOpen={isOpen}>
<DialogContent>
<div
style={{
display: `flex`,
width: `100%`,
alignItems: `center`,
justifyContent: `space-between`
}}
>
<h2 style={{ margin: `4px 0` }}>Modal Title</h2>
<button onClick={toggle}>Close</button>
</div>
{children}
</DialogContent>
</AnimatedDialogOverlay>
);
// )
// );
};
它渲染了三次,因为你的 return 组件有 transitions.map
因为你在
中有三个项目
from: { opacity: 0 }
enter: { opacity: 1 }
leave: { opacity: 0 }
当 isOpen
为真时,{children}
被调用了两次
您可以通过删除 from: { opacity: 0 }
和 leave: { opacity: 0 }
来解决问题
所以改变你的 modal.js => transitions
const transitions = useTransition(isOpen, null, {
enter: { opacity: 1 }
});
问题是,在动画结束时,AnotherComponent 重新装载。我阅读了关于 react-spring 的类似问题。一种方法是,将状态从 AnotherComponent 提升到 index.js。这样状态就不会在重新挂载时丢失,你可以防止重新获取数据。
const AnotherComponent = ({ url, todo, setTodo }) => {
useEffect(() => {
if (todo.length === 0) {
axios.get(url).then(res => setTodo(res.data));
}
});
....
}
我正在使用 react-spring 为基于 @reach/dialog 的模态框制作动画。 Modal 可以有任何 children。在 children 中,我正在根据一些道具获取一些数据。
问题是在打开模式时进行了两次提取调用。我认为这可能与我管理状态的方式有关,这导致 re-renders。
我试过在模态框内记忆 children 但没有用,所以我认为问题出在模态框组件之外。
这里有一些接近我的代码的东西以及它是如何工作的https://codesandbox.io/s/loving-liskov-1xouh
编辑:我已经知道,如果我删除 react-spring 动画,双重渲染不会发生,但我想尝试保持动画完好无损。
你觉得你能帮我找出错误在哪里吗? (也非常感谢一些关于钩子的良好实践的技巧)。
我查了一下,是因为Modal组件中的动画,当一个动画结束时渲染了两次,当我注释掉负责动画的fragment时,模态渲染了第二次,Modal只渲染了一次。
const Modal = ({ children, toggle, isOpen }) => {
// const transitions = useTransition(isOpen, null, {
// from: { opacity: 0 },
// enter: { opacity: 1 },
// leave: { opacity: 0 }
// });
console.log("render");
const AnimatedDialogOverlay = animated(DialogOverlay);
// return transitions.map(
// ({ item, key, props }) =>
// item && (
return (
<AnimatedDialogOverlay isOpen={isOpen}>
<DialogContent>
<div
style={{
display: `flex`,
width: `100%`,
alignItems: `center`,
justifyContent: `space-between`
}}
>
<h2 style={{ margin: `4px 0` }}>Modal Title</h2>
<button onClick={toggle}>Close</button>
</div>
{children}
</DialogContent>
</AnimatedDialogOverlay>
);
// )
// );
};
它渲染了三次,因为你的 return 组件有 transitions.map
因为你在
from: { opacity: 0 }
enter: { opacity: 1 }
leave: { opacity: 0 }
当 isOpen
为真时,{children}
被调用了两次
您可以通过删除 from: { opacity: 0 }
和 leave: { opacity: 0 }
所以改变你的 modal.js => transitions
const transitions = useTransition(isOpen, null, {
enter: { opacity: 1 }
});
问题是,在动画结束时,AnotherComponent 重新装载。我阅读了关于 react-spring 的类似问题。一种方法是,将状态从 AnotherComponent 提升到 index.js。这样状态就不会在重新挂载时丢失,你可以防止重新获取数据。
const AnotherComponent = ({ url, todo, setTodo }) => {
useEffect(() => {
if (todo.length === 0) {
axios.get(url).then(res => setTodo(res.data));
}
});
....
}