【发布时间】:2021-04-25 15:44:26
【问题描述】:
我正在尝试创建一个小组件,当它的一个方法被调用时,它会在它的子组件之间消失。我一直在关注this 代码,但它支持任意数量的孩子。到目前为止,我有这个:
export const Fader = React.forwardRef<FaderProps, Props>((props, ref) => {
const children = React.Children.toArray(props.children);
const [currentChild, setCurrentChild] = useState({
child: props.startIndex || 0,
direction: 1,
});
let nextChild = 0;
const fadeNext = (): void => {
queueNextFade(); //Queues the next fade which fades in the next child after the current child has faded out
setCurrentChild({
child: currentChild.child,
direction: +!currentChild.direction,
});
nextChild = currentChild.child + 1;
}
const fadePrev = (): void => {
}
const fadeTo = (index: number): void => {
}
const queueNextFade = (): void => {
setTimeout(() => {
setCurrentChild({
child: nextChild,
direction: +!currentChild.direction,
});
}, props.fadeTime || 500)
}
useImperativeHandle(ref, () => ({ fadeNext, fadePrev, fadeTo }));
return (
<div>
{
React.Children.map(children, (child, i) => (
<div key={i}
style={{
opacity: i === currentChild.child ? currentChild.direction : "0",
transition: `opacity ${props.fadeTime || 500}ms ease-in`,
}}
>
{child}
</div>
))
}
</div>
)
});
从逻辑上讲它确实有效,但实际发生的是第一个孩子淡出,但下一个孩子没有淡入。如果再次淡入,第二个孩子淡入然后淡出,下一个孩子淡入. (View in sandbox)
有一段时间我对为什么会发生这种情况感到困惑,因为我使用的逻辑与其他库相同。我做了一些研究,看看我是否可以让useState 变得即时,我遇到了this 的帖子,我引用了它:
即使你添加了
setTimeout函数,虽然超时会在重新渲染发生的一段时间后运行,但setTimeout仍将使用之前关闭的值,而不是更新后的值.
我意识到这就是我的情况。我启动setTimeout,其中currentChild.direction 是1。然后发生状态更改,方向更改为0。很长一段时间后,setTimeout 完成,但它没有将方向从 0 更改为 1,而是从 1 更改为 0,因为它保持了第一次调用时的原始值,因此为什么第二个孩子不会淡入,只是保持隐形。
我可以改成:
let currentChild = {...}
并且有一个“空白”useState 来充当forceUpdate,但我知道强制更新违背了 React 的本质,无论如何可能有更好的方法来做到这一点。
如果有人能帮忙,我会很感激的
【问题讨论】:
标签: reactjs