提问人:Mikkel Rank 提问时间:10/24/2023 最后编辑:Mikkel Rank 更新时间:10/24/2023 访问量:33
它如何呈现一个 React 列表,它依次从骨架到实际数据?
How do it render a React list where it sequentially goes from a skeleton to the actual data?
问:
介绍信息:我目前正在开发一个使用 TypeScript 的 React 项目。
在手头的项目中,我正在实现一个显示卡片的列表功能。在没有数据的情况下,会向用户显示骨架列表。一旦数据可用,列表就会转换以显示具有顺序效果的实际卡片,逐渐将不透明度从 0 更改为 1。
但是,我渴望实现更精致的过渡效果。具体来说,在加载状态期间,当骨架可见时,在获取数据时,我希望每个加载骨架按顺序过渡到其对应的卡片中,而不是让骨架完全消失,然后被卡片列表替换。
我所期望的过渡效果与Airbnb首页上观察到的效果非常相似。
我当前的实现类似于以下内容:
这是列表组件:
export const ListComponent = ({
data = [],
}) => {
const ref = useRef<HTMLDivElement>(null);
const [responsiveHeight, setResponsiveHeight] = useState(0);
const updateHeight = () => {
setTimeout(() => {
const gridItem = ref.current;
if (gridItem) {
const gridItemWidth = gridItem.clientWidth;
const newHeight = (gridItemWidth * 4) / 3.5;
setResponsiveHeight(newHeight);
}
}, 100);
};
useEffect(() => {
updateHeight();
window.addEventListener('resize', updateHeight);
return () => {
window.removeEventListener('resize', updateHeight);
};
}, []);
const columns = useMemo(() => {
if (isSm) return 1;
if (isLg) return 2;
return 3;
}, [isSm, isLg]);
if (data.length <= 0) return <ListSkeleton />;
return (
<Box minHeight={500}>
<Grid container columnSpacing={3} rowGap={isSm ? 3 : 6} columns={columns}>
{data.map((item, index) => (
<StyledGridItem
key={item.id}
ref={ref}
index={index}
item
xs={1}
>
<Card
item={item}
height={responsiveHeight}
/>
</StyledGridItem>
))}
</Grid>
</Box>
);
};
const fadeIn = keyframes`
from { opacity: 0; }
to { opacity: 1; }
`;
const StyledGridItem = styled(Grid)<{ index: number }>`
opacity: 0;
animation: ${fadeIn} 0.3s ease-in-out forwards;
animation-delay: ${(props) => props.index * 0.075}s;
`;
这是列表项组件:
export const Card = ({
item,
height
}) => {
const router = useRouter();
return (
<a href={`/example`} >
<StyledCard maxHeight={Math.min(height, 464)}>
<CardImage src={item.image} height={height} />
<CardDetails item={item} />
</StyledCard>
</a>
);
};
const StyledCard = styled(Stack)`
position: relative;
width: 100%;
border-radius: 12px;
box-shadow: ${Theme.shadows.medium};
:hover {
filter: brightness(95%);
box-shadow: ${Theme.shadows.large};
}
`;
我曾尝试使用 React-spring 解决这个问题,但没有任何成功 - 并且认为每张卡可能都应该显示它们自己的骨架。
答: 暂无答案
下一个:创建动画轮播的代码是什么?
评论