eiriklv / react-masonry-component

A React.js component for using @desandro's Masonry
MIT License
1.44k stars 145 forks source link

Bad position/placement if element is prepended in array #11

Open johankvint opened 8 years ago

johankvint commented 8 years ago

I have an array with elements that I get from filtering a larger array base on some value. I give the children to the masonry unique keys. This works great when the visible child at position 0 in array remains visible all the time. But when a child gets prepended in the array the child elements start to overlap.

class CategoryPage extends React.Component {

  static propTypes = {
    category: PropTypes.string.isRequired,
  }

  getCategory = () => {
    const { category } = this.props;
    return categories
              .filter((cat) => {
                return cat.params.category === category;
              })[0];
  }

  render() {
    const { items } = this.props;
    const options = {
      gutter: 0,
      isFitWidth: true
    }

    const current = this.getCategory();

    const filtered = items
      .filter(item => {
        return item.categories.some((category) => {
            return current.tags.indexOf(category) !== -1;
        });
      })
      .map(item => {
        return (
          <Card
            key={item.id}
            id={item.id}
            title={item.title}
            image={item.image}
            description={item.description}
            categories={item.categories} />
        );
      });

    return (
      <div>
        <div className="background-transition" style={{'background': current.color, 'padding': '20px 0'}}>
          <div className="container align-center">
            <h2>{ current.text }</h2>
          </div>
        </div>
        <div className="container align-center">
            <Masonry
              options={options}
              disableImagesLoaded={true} >
              {filtered}
            </Masonry>
        </div>
      </div>
    );
  }
}

export default CategoryPage;
eiriklv commented 8 years ago

And all id's are unique? Seems like an edge case issue when doing prepending to the masonry.. Might be that the "algorithm" for diffing does not account for this. What happens if you always include a dummy element at the top that is "invisible"?

afram commented 8 years ago

@cybercomkvint can you please try the 3.0.0 beta and see if it fixes things for you?

npm install --save react-masonry-component@3.0.0-rc.1

You no longer need to pass in React to a function - also a little extra setup required if using Webpack. More info in Readme

terencechow commented 8 years ago

I had the same problem and can confirm using 3.0.0-rc.1 does not fix it. However using a dummy element does fix it. Quite odd..

I am using a div with width 1px and height 0px which surprisingly does the trick. If I use an empty div with no styling, it causes all the masonry elements to be stacked vertically despite having plenty of space to be layed out horizontally.

wkw commented 8 years ago

Also hit this buglet. Same situation, I have a list of items and the ability to filter the set. When going from a filtered view to the "All Items" view, I end up with stacking, empty space in first row. I spent time trying to "kick" masonry to re-layout in componentDidUpdate (didn't work), then tried calling masonry.layout() in a setTimer(). No work.

I next did the horrible thing of making my element array key properties always random. that fixed it, but had unwanted side-effects for certain other modal views.

Adding the empty div as first element of every filtered view solved the problem.

jarindr commented 8 years ago

Thank god I saw this issue, was trying to figure out what's happening with my layout with filtering involved. Hacked with div height 1 width 1 just the same.