动态显示相同项目的照片,如果只有一张照片则隐藏轮播

Dynamically display photos of same item and hide carousel if there is only one photo

在 React 应用程序中,我显示每个项目的 1-5 张照片。所有照片都在 Node 下的文件夹中,所以我显示它们的方式是使用它们的 url,即 http://10.1.1.1:3000/01-0001.JPG 所以,我没有发出 http 请求来获取它们。

问题是:

无法知道每件商品有多少张照片。例如,一件商品可能有 5 张照片,而另一件商品只有一张照片。文件名的格式是这样的:01-0001.JPG, 01-0001.1.JPG, 01-0001.2.JPG

所以,我现在做的是:

    const Item1 = () => {
      return (
        <img src={`${process.env.REACT_APP_NODE_SERVER}/${item.No}.JPG`} onError={this.addDefaultSrc} alt='1'></img>
      )
    }

    const Item2 = () => {
      return (
        <img src={`${process.env.REACT_APP_NODE_SERVER}/${item.No}.1.JPG`} onError={this.addDefaultSrc} alt='2'></img>
      )
    }

    const Item3 = () => {
      return (
        <img src={`${process.env.REACT_APP_NODE_SERVER}/${item.No}.2.JPG`} onError={this.addDefaultSrc} alt='3'></img>
      )
    }

我用这个功能在没有照片的时候显示一张虚拟照片

  addDefaultSrc(ev) {
    ev.target.src = `${process.env.REACT_APP_NODE_SERVER}/notfound.png`;
    ev.target.onerror = null;
  }

这是一个糟糕的解决方案,因为我不希望客户看到虚拟图片,相反,客户应该只看到每件商品的真实照片数量。

我正在使用 react-multi-carousel

          <Carousel
          responsive={responsive}
          swipeable={false}
          draggable={false}
          showDots={true}
          ssr={false} // means to render carousel on server-side.
          infinite={false}
          autoPlay={false}
          autoPlaySpeed={1000}
          keyBoardControl={true}
          customTransition="all .5"
          transitionDuration={500}
          containerClass="carousel-container"
          removeArrowOnDeviceType={["tablet", "mobile"]}
          deviceType={this.props.deviceType}
          dotListClass="custom-dot-list-style"
          itemClass="carousel-item-padding-40-px">
            <div><Item1 /></div>
            <div><Item2 /></div>
            <div><Item3 /></div>
          </Carousel>

如有任何帮助,我们将不胜感激。

我认为您应该遍历图像,将初始样式设置为 display: none,等待所有回调并在一切完成后计算适当的状态。

例子

const { useState, useEffect } = React;

const random = () => Math.floor(Math.random() * 5 + 5);
const getImages = () => Promise.resolve(Array(random()).fill(0).map((pr, index) => {

  const id = index + 750;

  return {
    id,
    url: `https://i.picsum.photos/id/${id}/100/100.jpg`,
    loaded: false,
    error: false,
    alt: id
  }
}))

const Images = ({onComplete}) => {
  const [images, setImages] = useState([]);
  const [allLoaded, setLoaded] = useState(false);
  
  useEffect(() => {
    let isUnmounted = false;
    
    getImages()
      .then(images => {
        if(isUnmounted) {
          return;
        }
        
        setImages(images);
      })
      
    return () => {
      isUnmounted = true;
    }
  }, [])
  
  useEffect(() => {
    let isUnmounted = false;
  
    const loadedImagesCount = images.reduce((acc, image) => acc + Number(image.error) + Number(image.loaded), 0);

    if(images.length === loadedImagesCount) {
      setTimeout(() => {
        if(isUnmounted) {
          return;
        }
        
        setLoaded(true);
        onComplete();
      }, 500);
    }
    
    return () => {
      isUnmounted = true;
    }
  }, [images])
  
  const onError = id => {
    setImages(images => {
      const imageIndex = images.findIndex(image => image.id ===id)
      const image = images[imageIndex];
      
      return [
        ...images.slice(0, imageIndex),
        {
          ...image,
          error: true
        },
        ...images.slice(imageIndex + 1)
      ]
    })
  }
  
  const onLoad = id => {
    setImages(images => {

      const imageIndex = images.findIndex(image => image.id ===id)
      const image = images[imageIndex];
      
      return [
        ...images.slice(0, imageIndex),
        {
          ...image,
          loaded: true
        },
        ...images.slice(imageIndex + 1)
      ]
    })
  }
  
  const loadedImagesCount = images.reduce((acc, image) => acc + Number(image.loaded), 0)
  
  if(allLoaded && [0, 1].includes(loadedImagesCount)) {
    return 'No images or only one image - hidden'
  }
  
  return <React.Fragment>
    {images.map(({id, loaded, error, url, alt}) => <img key={id} src={url} className={`image ${error ? 'image--error' : null} ${allLoaded && loaded ? 'image--loaded' : null}`} onLoad={() => onLoad(id)} onError={() => onError(id)} alt={alt}/>)}
  </React.Fragment>
}

const App = () => {
  const [loading, setLoading] = useState(true);

  const onComplete = () => {
    setLoading(false);
  }

  return <div>
    {loading ? 'Loading...' : null}
    <Images onComplete={onComplete}/>
  </div>
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
  );
.image {
  display: none;
}

.image--error {
  display: none;
}

.image--loaded {
  display: inline;
}
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>