react-photo-gallery don't change photos via state

655 Views Asked by At

The photo object is not changing in the Gallery component via state. I created a "folder gallery", a multi gallery component to render a new one if you select it by click.

See the demonstration: https://codesandbox.io/s/50wr02n8q4

github issue: https://github.com/neptunian/react-photo-gallery/issues/118

Envs:

  • react-photo-gallery: 6.2.2
  • react: 16.6.3
  • npm: 6.4.1

See the code below:

const folderPhotos = [
  {
    title: "Gallery one",
    photos: [
      {
        src: "https://source.unsplash.com/2ShvY8Lf6l0/800x599"
      },
      {
        src: "https://source.unsplash.com/Dm-qxdynoEc/800x799"
      },
      {
        src: "https://source.unsplash.com/qDkso9nvCg0/600x799"
      }
    ]
  },
  {
    title: "Gallery two",
    photos: [
      {
        src: "https://source.unsplash.com/iecJiKe_RNg/600x799"
      },
      {
        src: "https://source.unsplash.com/epcsn8Ed8kY/600x799"
      },
      {
        src: "https://source.unsplash.com/NQSWvyVRIJk/800x599"
      }
    ]
  }
];

The photoProps dimensions object:

const photoProps = {
    width: 1,
    height: 1
  };

The internal component here:

<Gallery
        columnsLength={6}
        photosObj={folderPhotos}
        photoProps={photoProps}
        withLightbox={true}
      />

Now the Gallery component:

import _ from "lodash";
import React, { Component, Fragment } from "react";
import Gallery from "react-photo-gallery";
import Lightbox from "react-images";

export class PhotoGallery extends Component {
  constructor(props) {
    super(props);

    // Bindables
    this.showGallery = this.showGallery.bind(this);
    this.openLightbox = this.openLightbox.bind(this);
    this.closeLightbox = this.closeLightbox.bind(this);
    this.goToPrevious = this.goToPrevious.bind(this);
    this.goToNext = this.goToNext.bind(this);
  }

  state = {
    photosObj: [],
    currentImage: 0,
    lightboxIsOpen: false
  };

  async showGallery(itemObj, photoProps) {
    let photosObj = [];

    if (!_.isEmpty(itemObj)) {
      photosObj = await Object.keys(itemObj)
        .map(i => itemObj[i])
        .map(item => ({
          ...item,
          width: photoProps.width,
          height: photoProps.height
        }));

      this.setState({
        photosObj
      });

      console.log("-- props: ", this.state.photosObj);
    }
  }

  openLightbox(event, obj) {
    this.setState({
      currentImage: obj.index,
      lightboxIsOpen: true
    });
  }

  closeLightbox() {
    this.setState({
      currentImage: 0,
      lightboxIsOpen: false
    });
  }

  goToPrevious() {
    this.setState({
      currentImage: this.state.currentImage - 1
    });
  }

  goToNext() {
    this.setState({
      currentImage: this.state.currentImage + 1
    });
  }

  render() {
    const { columnsLength, photosObj, photoProps, withLightbox } = this.props;
    return (
      <div className="section-body">
        <div className="content-col-info">
          <ul className="list-mentors w-list-unstyled">
            {photosObj.map((itemObj, i) => (
              <li key={i}>
                <span
                  className="mentors-item w-inline-block"
                  onClick={() => this.showGallery(itemObj.photos, photoProps)}
                >
                  <div>{itemObj.title}</div>
                </span>
              </li>
            ))}
          </ul>
        </div>

        <div className="content-col-info">
          {!_.isEmpty(this.state.photosObj) && (
            <Gallery
              columns={columnsLength}
              photos={this.state.photosObj}
              onClick={withLightbox ? this.openLightbox : null}
            />
          )}

          {!_.isEmpty(this.state.photosObj) && withLightbox && (
            <Lightbox
              images={this.state.photosObj}
              onClose={this.closeLightbox}
              onClickPrev={this.goToPrevious}
              onClickNext={this.goToNext}
              currentImage={this.state.currentImage}
              isOpen={this.state.lightboxIsOpen}
            />
          )}
        </div>
      </div>
    );
  }
}

export default PhotoGallery;

EDIT - I updated the Gallery props

I fix the Gallery component props of the example too.

loadGallery(columnsLength) {
    import("./photo-gallery").then(Gallery => {
      console.log("-- load gallery: ", this.state.photosObj);

      return (
        <Gallery.default
          columnsLength={columnsLength}
          photosObj={this.state.photosObj}
          withLightbox={true}
        />
      );
    });
  }

And to call this:

{!_.isEmpty(this.state.photosObj) && this.loadGallery(columnsLength)}

References:

1

There are 1 best solutions below

0
On

Since photos option is required in Gallery.js (Library)

Gallery.propTypes = {
  photos: _propTypes2.default.arrayOf(_Photo.photoPropType).isRequired,
  direction: _propTypes2.default.string,
  onClick: _propTypes2.default.func,
  columns: _propTypes2.default.number,
  margin: _propTypes2.default.number,
  ImageComponent: _propTypes2.default.func
};

Pass "photos={this.state.photosObj}" in <Gallery /> of Gallery.js (your js file) as follows:

Code:

<Gallery
  columnsLength={columnsLength}
  photosObj={this.state.photosObj}
  photos={this.state.photosObj}
  withLightbox={true}
 />

I am not sure why you pass other options.