提问人:Garrett Rozsa 提问时间:10/20/2023 更新时间:10/20/2023 访问量:15
当用户选择产品时,如何使用效果和参考来设置自动滚动行为?
How do I use effects and refs to set an automatic scroll behavoir when a user selects a product?
问:
我正在使用 tailwind CSS 在 Next 中工作。目标是设置一个商店页面,其行为类似于 instagram 提要,用户在其中单击网格中的产品照片,该页面在占据整个视口的 FeaturedProduct 卡片上呈现所有相同的内容,并且可以滚动以查看整个目录,其显示顺序与在 renderProductList 中定义的网格视图中的显示顺序相同。
这个组件几乎是完美的。为了完成它,我需要在布局更改以响应用户单击产品时滚动到视图中。
import React, { useContext, useState, useEffect, useRef } from 'react';
import FeaturedProduct from '@/components/featured-product';
import { ProductsContext } from '@/context/products-context';
const Home = () => {
const [selectedProduct, setSelectedProduct] = useState(null);
const products = useContext(ProductsContext);
const containerRef = useRef(null);
const productRefs = useRef([]);
const handleProductClick = (product) => {
setSelectedProduct(product);
};
useEffect(() => {
console.log('useEffect called');
if (selectedProduct && productRefs.current[selectedProduct.id]) {
const productElement = productRefs.current[selectedProduct.id];
const containerElement = containerRef.current;
if (productElement && containerElement) {
const containerRect = containerElement.getBoundingClientRect();
const productRect = productElement.getBoundingClientRect();
const offset = productRect.top - containerRect.top - (containerRect.height - productRect.height) / 2;
containerElement.scrollBy({
top: offset,
behavior: 'auto',
});
}
}
}, [selectedProduct]);
const renderProductList = () => {
return (
<div className='grid grid-cols-3 gap-4' ref={containerRef}>
{products.map((product, index) => (
<div
key={product.id}
ref={(el) => (productRefs.current[product.id] = el)}
onClick={() => handleProductClick(product)}
>
<img
src={product.imageUrl}
alt={product.title}
className='w-full h-auto cursor-pointer'
/>
</div>
))}
</div>
);
};
const renderFullScreenProduct = () => {
if (!selectedProduct) return null;
const selectedProductIndex = products.findIndex((product) => product.id === selectedProduct.id);
const allProducts = products.map((product, index) => (
<div key={product.id} ref={(el) => index === selectedProductIndex && el}>
<FeaturedProduct { ...product } key={product.id} />
</div>
));
return (
<div className='fixed top-0 left-0 w-full h-full overflow-y-auto bg-white'>
<div className='max-w-screen-md mx-auto p-4' >
{allProducts}
<button
className='absolute top-4 right-4 text-gray-600'
onClick={() => setSelectedProduct(null)}
>
Close
</button>
</div>
</div>
);
};
return (
<div className='mx-4'>
{selectedProduct ? renderFullScreenProduct() : renderProductList()}
</div>
);
};
export default Home;
这是我得到的最好的。我没有足够的经验使用 useRef 和 useEffect 来使这项工作对我有利。我想重申,这个组件的行为几乎完全符合我的需要。设置自动滚动行为似乎是一件非常容易的事情,我相信解决方案比我想出的这个绝对混乱要优雅得多。
答: 暂无答案
评论