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

时间:2020-06-01 12:58:14

标签: node.js reactjs carousel

在react应用程序中,我显示每个项目的1-5张照片。所有照片都位于Node下的文件夹中,因此我显示照片的方式是使用其网址,即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>

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

我认为您应该遍历图像,将初始样式设置为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>