arrays - 在反应钩子中使用一组图像在图像网格和图像滑块之间切换
问题描述
我正在使用 Nextjs、React 和使用 Sanity 作为 CMS 构建一个项目。
其中一个主要组件将是一个图像库,当您单击图像时,您将打开一个图像滑块库。图像是从 CMS 传入的数组。
它大致基于该网站的工作方式.. https://www.garrodkirkwood.com/projects/
目前,我正在使用一个简单的 setState 切换来隐藏和显示图片库和幻灯片。代码远非完美,因为我意识到发生了很多事情。
我需要什么帮助......
我需要找到一种方法将单击图像的索引传递给事件侦听器,以便在单击图像时打开相同图像上的幻灯片。
我真的希望这是有道理的。
然后,用户将通过单击“显示缩略图”退出幻灯片
从“react”导入反应,{ useState,useEffect,useRef }; 从“@emotion/core”导入 { css, jsx }; 从“./ImageSliderContent”导入 ImageSliderContent; 从“./ImageGrid.module.css”导入样式; 从“./ImageGrid”导入 ImageGrid; 从“./ImageSlide”导入 ImageSlide; 从“./Arrow”导入箭头; 从“./Dots”导入点; 从“@sanity/image-url”导入 imageUrlBuilder; 从“../../client”导入客户端; const builder = imageUrlBuilder(client); const LocationsImageGallery = (props) => { 常量 { 标题,图像 } = 道具; 常量图像 = props.image; const [状态,setState] = useState({ 翻译:0, 过渡:0.45, 活动幻灯片:0, }); 常量 [showSlider, setShowSlider] = useState(false); 常量 { 翻译,过渡,activeSlide,_slides } = 状态; 常量大小 = useWindowSize(); 常量 transitionRef = useRef(); 函数 useWindowSize() { const isClient = typeof window === "object"; 函数 getSize() { 返回 { 宽度:是客户端?window.innerWidth :未定义, }; } const [windowSize, setWindowSize] = useState(getSize); 使用效果(()=> { 如果(!isClient){ 返回假; } 函数句柄调整大小(){ setWindowSize(getSize()); } window.addEventListener("resize", handleResize); return () => window.removeEventListener("resize", handleResize); }, []); 返回窗口大小; } 常量 nextSlide = () => { if (activeSlide === images.length - 1) { 返回集合状态({ ...状态, 翻译:0, 活动幻灯片:0, }); } 设置状态({ ...状态, 活动幻灯片:活动幻灯片+ 1, 翻译:(activeSlide + 1)* size.width, }); }; 常量 prevSlide = () => { if (activeSlide === 0) { 返回集合状态({ ...状态, 翻译:(images.length - 1)* size.width, activeSlide: images.length - 1, }); } 设置状态({ ...状态, 活动幻灯片:活动幻灯片 - 1, 翻译:(activeSlide - 1)* size.width, }); }; 常量显示 = () => { 设置显示滑块(真); }; 常量隐藏 = () => { 设置显示滑块(假); }; 返回 ( <div className={styles.root}> <div className={styles.imageGridContainer}> {images.map((图像,索引)=>( <div className={styles.imageContainer} onClick={show}> <img src={builder.image(image).auto("format").width(2000).url()} 类名={styles.image} alt={图片说明} 键={索引} /> <p className={styles.caption}>{image.caption}</p> </div> ))} </div> {显示滑块 && ( <div className={styles.imageGalleryContainer}> <div css={ImageSliderCSS}> <ImageSlider 内容 翻译={翻译} 过渡={过渡} 宽度={大小.宽度*图像.长度} > {images.map((图像,索引)=>( <图片幻灯片 键={图像 + 索引} 内容={builder.image(image).auto("格式").width(2000).url()} ></ImageSlide> ))} </ImageSliderContent> <箭头方向=“左”handleClick={prevSlide} /> <箭头方向=“右”handleClick={nextSlide} /> <点幻灯片={图像} activeSlide={activeSlide} /> </div> <a href="" onClick={隐藏}> 显示缩略图 </a> </div> )} </div> ); }; 常量 ImageSliderCSS = css` 位置:相对; 高度:500px; 宽度:750px; 边距:0 自动; 溢出:隐藏; `; 导出默认 LocationsImageGallery;
更新了通过索引点击事件
import React, { useState, useEffect, useRef } from "react";
import { css, jsx } from "@emotion/core";
import ImageSliderContent from "./ImageSliderContent";
import styles from "./LocationsImageGallery.module.css";
import ImageGrid from "./ImageGrid";
import ImageSlide from "./ImageSlide";
import Arrow from "./Arrow";
import Dots from "./Dots";
import imageUrlBuilder from "@sanity/image-url";
import client from "../../client";
const builder = imageUrlBuilder(client);
const LocationsImageGallery = (props) => {
const { caption, image } = props;
const images = props.image;
const [state, setState] = useState({
translate: 0,
transition: 0.45,
activeSlide: 0,
});
const [showSlider, setShowSlider] = useState(false);
const [showGrid, setShowGrid] = useState(true);
const { translate, transition, activeSlide, _slides } = state;
const size = useWindowSize();
const transitionRef = useRef();
function useWindowSize() {
const isClient = typeof window === "object";
function getSize() {
return {
width: isClient ? window.innerWidth : undefined,
};
}
const [windowSize, setWindowSize] = useState(getSize);
useEffect(() => {
if (!isClient) {
return false;
}
function handleResize() {
setWindowSize(getSize());
}
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return windowSize;
}
const nextSlide = () => {
if (activeSlide === images.length - 1) {
return setState({
...state,
translate: 0,
activeSlide: 0,
});
}
setState({
...state,
activeSlide: activeSlide + 1,
translate: (activeSlide + 1) * size.width,
});
};
const prevSlide = () => {
if (activeSlide === 0) {
return setState({
...state,
translate: (images.length - 1) * size.width,
activeSlide: images.length - 1,
});
}
setState({
...state,
activeSlide: activeSlide - 1,
translate: (activeSlide - 1) * size.width,
});
};
const show = (index) => {
setShowGrid(false);
setShowSlider(true);
setState({ activeSlide: index });
};
const hide = () => {
setShowSlider(false);
setShowGrid(true);
};
return (
<div className={styles.root}>
<div className={styles.header}>
<a href="/locations">X</a>
</div>
{showGrid && (
<div className={styles.imageGrid}>
<div className={styles.imageGridContainer}>
{images.map((image, index, caption) => (
<div className={styles.imageContainer} onClick={() => show(index)}>
<img
src={builder.image(image).auto("format").width(2000).url()}
className={styles.image}
alt={image.caption}
key={index}
/>
<p className={styles.caption}>{image.caption}</p>
</div>
))}
</div>
</div>
)}
{showSlider && (
<div className={styles.imageGalleryContainer}>
<div className={styles.imageSlider}>
<ImageSliderContent
translate={translate}
transition={transition}
width={size.width * images.length}
>
{images.map((image, index, caption) => (
<>
<ImageSlide
key={image + index}
content={builder.image(image).auto("format").url()}
></ImageSlide>
</>
))}
</ImageSliderContent>
<Arrow direction="left" handleClick={prevSlide} />
<Arrow direction="right" handleClick={nextSlide} />
</div>
<div className={styles.infoBar}>
<p className={styles.infoCaption}>
Locations / <span>{image.caption}</span>
</p>
<a href="" onClick={hide} className={styles.infoThumbnails}>
Show Thumbnails
</a>
</div>
</div>
)}
</div>
);
};
export default LocationsImageGallery;
这个版本,好像没有更新状态,activeSlide的console.log和状态...
LocationsImageGallery.js?0692:94 {activeSlide: 8, state: {…}} activeSlide: 8 state: activeSlide: 0 transition: 0.45 translate: 0 proto: Object proto: Object
解决方案
您能否尝试将自定义属性添加到 img 元素,并将索引作为值,例如
data-index = {index}
然后,您可以回到原来的方式来执行 onClick 处理程序
onClick={show}
然后,您的 show 函数可以像这样获取该自定义属性:
const show = (e) => {
setShowGrid(false);
setShowSlider(true);
setState({ activeSlide: e.target.getAttribute("data-index") });
};
推荐阅读
- spring-boot - 如何在 Spring Boot 2.0 中使用 Redis 作为数据库映射两个实体之间的关系?
- amazon-sagemaker - 无法使用 sagemaker 调用端点
- android - 向上滑动刷新后仅调用 LoadInitial 的分页库调用,而不调用 LoadAfter
- bash - 当行与 sed 完全匹配另一个字符串时,将字符串替换为另一个字符串
- opengl - glTexImage2D() 参数和生成帧缓冲区
- android - 替换 AppCompatActivity 中的片段
- react-native - 将值动态传递给子组件反应原生
- javascript - 使用 ajax 处理两个回显响应
- android - 如何从 JSON 对象中获取字符串数组
- angular - 使用 ngsubmit="onSubmit()" 的 Angular 6 表单