bugfix> javascript > 投稿

この画像ライトボックスをReactアプリで使用しようとしています:

https://www.w3schools.com/howto/howto_js_lightbox.asp

これは、試したコードサンドボックスリンクです

https://codesandbox.io/s/reactjs-practice-vbxwt

画像モーダルは私にとってはうまく機能します。しかし、スライダーを実装しようとすると機能しないようです。各リストにスライダーを実装したいと思います。バックエンドから画像データを取得しています。

これが私がすべての画像データを取得する方法です:

{
    "results": [{
        "data": [{
            "id": "f06f2cdf-1bb8-4388-a655-4e916a2703ce",
            "visitRequirementList": [{
                "imageName": "dining pic 1",
                "imagePath": "visitImageDirectory/0297b1ef-644b-45fc-9760-4e5693f54ac0.png",
            }, {
                "imageName": "dining pic 2",
                "imagePath": "visitImageDirectory/1b4915c1-733a-4bdb-a8d7-59ce3a095d44.png",
            }]
        }, {
            "id": "ce059d7a-d3d4-462c-a90f-62be13f24a29",
            "visitRequirementList": [{
                "imageName": "bedroom pic 1",
                "imagePath": "visitImageDirectory/64960b86-f9bf-4de9-816f-f27487245c53.png",
            }]
        }]
    }],
    "message": "data Found",
    "status": "success"
}

これは私の render 画像を表示する方法:

import React, { Component } from 'react';
export default class extends Component {
    state = {
        showModal: false,
        caption: '',
        modalSrc: '',
        ioImageListing: [],
        // ...rest of the state
    };
    componentDidMount() {
        this.getAllProjectRequirementImageList();
    }
    getAllProjectRequirementImageList = () => {
        axios.get(this.state.apiUrl+'/api/v1/visitRequirement/getAllByProjectId', {
            params: {   projectId: this.state.projectId }
        }).then((response) => {
            console.log("get with list ImageData",response.data.data);
            this.setState({ ioImageListing: response.data.data  });
        }).catch((error)=>{  console.log("error",error); this.setState({ ioImageListing: []  });   });
    }
    render() {
        return (
            <div>
                <div style={{}}>
                    {this.state.ioImageListing.map((io, key) =>
                        <Grid container spacing={24}>
                            {io.visitRequirementList.map((pic, key) => [
                                <Grid style={{position: 'relative'}} item xs={3} key={key}>
                                <span key={key}>
                                    <img
                                        src={this.state.apiUrl + '/api/v1/visitImageRequirementInfo/getImageByImagePathId?imagePath=' + pic.imagePath}
                                        onClick={() => {
                                            this.setState({
                                                showModal: true,
                                                caption: `${pic.imageName}`,
                                                slideIndex: `${io.visitRequirementList.length}`,
                                                modalSrc: `${this.state.apiUrl}/api/v1/visitImageRequirementInfo/getImageByImagePathId?imagePath=${pic.imagePath}`,
                                                count: `${key}`
                                            });
                                        }}
                                    />
                                </span>
                                </Grid>
                            ])}
                        </Grid>
                    )}
                </div>
                <div id="myModal" className="modal" style={{display: this.state.showModal ? 'block' : 'none'}}>
                    <div>
                        <span className="close" onClick={() => this.setState({showModal: false})}>&times;</span>
                        <div className="mySlides"><img className="modal-content" id="img01" src={this.state.modalSrc}/>
                        </div>
                        <a className="prev" onClick={() => {
                            this.plusSlides(-1)
                        }}>&#10094;</a>
                        <a className="next" onClick={() => {
                            this.plusSlides(1)
                        }}>&#10095;</a>
                    </div>
                </div>
            </div>
        );
    }
}

そして、これは私がスライダーを表示するために書いた関数です:

   plusSlides = (n) => {
        var slideIndex=parseFloat(this.state.count);
        slideIndex=slideIndex+n
        this.setState({ count: slideIndex  });
        this.showSlides(slideIndex, n);
    }
  showSlides(slideIndex,n) {
        var i;
        var slides = document.getElementsByClassName("mySlides");
        if (n > slides.length) {slideIndex = 1}
        if (n < 1) {slideIndex = slides.length}
        for (i = 1; i < slides.length; i++) {
            slides[i].style.display = "none";
        }
        slides[slideIndex-1].style.display = "block";
    }

画像モーダルが開いたら、次と前のボタンをクリックするとスライドになります。私は何を間違っていますか?

回答 2 件
  • まず第一に、あなたはReactを正しい方法で使用していません。関数 showSlides DOM操作を直接使用します。 DOMを直接操作するのではなく、常に更新してください。 state 希望の値に調整し、ReactにDOMを処理させます。

    そうは言っても、スライダーを更新するだけで、スライダーがどのように反応的に機能するかを説明しましょう。 state 。これまでのところ、モーダルを機能させることができました。スライダーロジックは次のようになります(コードサンドボックスリンク):

    imageListDataはリストのリストです。わかりやすくするために、外側のリストを次のように参照します。 section

    1-画像をクリックしたら、次のデータで状態を更新します。

    showModal // to toggle the visibility of modal
    caption // caption for current image
    modalSrc // current image source
    sectionIndex // current index of outer list
    imageIndex // index of current image
    currentSectionLength // outer list, i.e. section length
    
    

    2-クリックすると Next または Previous ボタンをクリックすると、手順1で説明した状態のみが更新され、スライダーが機能します。考慮すべき唯一のことは、状態を正しい値で更新するロジックです。コメントで説明しようと思います。すべてのロジックがあります plusSlides 関数。

    plusSlides = n => {
        const { ioImageListing, imageIndex, sectionIndex, currentSectionLength } = this.state; // extract all the current values from the state
        const nextIndex = imageIndex + n; // add or subtract 1 to get nextIndex. This is temporary. We will use this to determine next image on the slider.
        const numberOfSections = ioImageListing.length; // count of number of outer list.
        if (nextIndex < 0 && sectionIndex === 0) {
          // this means we are at the 1st image of 1st section. Hence no more left navigation, and the function returns. No more execution.
          alert("NO MORE LEFT IMAGE");
          return;
        }
        if (sectionIndex === numberOfSections - 1 && nextIndex > ioImageListing[numberOfSections - 1].visitRequirementList.length - 1) {
          // this condition says we are at the last image of last section. Hence no more right navigation, and the function returns. No more execution.
          alert("NO MORE RIGHT IMAGE");
          return;
        }
        let nextImage, nextImageIndex, nextSectionIndex, nextSectionLength; // these variables will hold the value for next image to be shown determined by the following logic
        if (nextIndex >= 0 && nextIndex < currentSectionLength) {
          // if the nextIndex is >=0 and less than the length of currentSectionLength, it means our next/previous image is in the same section. So we only need to update nextImage data whereas section data remains same
          nextImage = ioImageListing[sectionIndex].visitRequirementList[nextIndex];
          nextImageIndex = nextIndex;
          nextSectionIndex = sectionIndex;
          nextSectionLength = currentSectionLength;
        } else if (nextIndex < 0) {
          // if the nextIndex is less than 0, it means our previous image is in the previous section and it has to be the last image of previous section. So we update both nextImage data and section data accordingly.
          nextImage = ioImageListing[sectionIndex - 1].visitRequirementList[ioImageListing[sectionIndex - 1].visitRequirementList.length - 1];
          nextImageIndex = ioImageListing[sectionIndex - 1].visitRequirementList.length - 1;
          nextSectionIndex = sectionIndex - 1;
          nextSectionLength = ioImageListing[sectionIndex - 1].visitRequirementList.length
        } else {
          // atlast if the nextIndex >= currentSectionLength, it means our next image is in the next section and it has to be the first image of next section. So we update both nextImage data and section data accordingly.
          nextImage = ioImageListing[sectionIndex + 1].visitRequirementList[0];
          nextImageIndex = 0;
          nextSectionIndex = sectionIndex + 1;
          nextSectionLength = ioImageListing[sectionIndex + 1].visitRequirementList.length;
        }
        // finally we update the state with current next values, and the slider works as expected.
        this.setState({
          caption: nextImage.imageName,
          modalSrc: nextImage.imagePath,
          imageIndex:nextImageIndex,
          sectionIndex: nextSectionIndex,
          currentSectionLength:nextSectionLength
        });
      }
    
    

    お役に立てば幸いです。疑問があれば教えてください。作業コードはリンクから入手できます

  • 画像を配列に保存する必要があります。これらの画像を状態に保存してから、「mySlides」内のimgを次のように変更します。

    /** -- snip -- **/
    // Inside of "mySlides" div
    <img 
        className="modal-content" 
        id="img01" 
        src={this.state.images[this.state.count]}
    />
    
    

あなたの答え