Giter VIP home page Giter VIP logo

react-masonry-component's Introduction

React Masonry Component

npm version Build Status

IE8 support

if you wish to have IE8 support, v2 with React 0.14 is the highest version available.

Table of contents

  1. Usage
  2. Basic usage
  3. Custom props
  4. Accessing Masonry instance
  5. Images Loaded Options
  6. Events

Introduction:

A React.js Masonry component. (Also available as a mixin if needed)

Live demo:

hearsay.me

Usage:

  • The component is bundled with Masonry, so no additional dependencies needed!

  • You can optionally include Masonry as a script tag if there should be any reason for doing so <script src='//cdnjs.cloudflare.com/ajax/libs/masonry/3.1.5/masonry.pkgd.min.js' />

  • To use the component just require the module.

Basic usage

npm install --save react-masonry-component

import * as React from 'react';
import Masonry from 'react-masonry-component';

const masonryOptions = {
    transitionDuration: 0
};

const imagesLoadedOptions = { background: '.my-bg-image-el' }

class Gallery extends React.Component {
    render() {
        const childElements = this.props.elements.map(function(element){
           return (
                <li className="image-element-class">
                    <img src={element.src} />
                </li>
            );
        });
    
        return (
            <Masonry
                className={'my-gallery-class'} // default ''
                elementType={'ul'} // default 'div'
                options={masonryOptions} // default {}
                disableImagesLoaded={false} // default false
                updateOnEachImageLoad={false} // default false and works only if disableImagesLoaded is false
                imagesLoadedOptions={imagesLoadedOptions} // default {}
            >
                {childElements}
            </Masonry>
        );
    }
}

export default Gallery;

ES6-style modules are also supported, just use:

import Masonry from 'react-masonry-component';
Custom props

You can also include your own custom props - EG: inline-style and event handlers.

import * as React from 'react';
import Masonry from 'react-masonry-component';

const masonryOptions = {
    transitionDuration: 0
};

const style = {
    backgroundColor: 'tomato'
};

class Gallery extends React.Component {
    handleClick() {}
    render() {
        return (
            <Masonry
                className={'my-gallery-class'}
                style={style}
                onClick={this.handleClick}
            >
                {...}
            </Masonry>
        );
    }
}

export default Gallery;
Accessing Masonry instance

Should you need to access the instance of Masonry (for example to listen to masonry events) you can do so by using refs.

import * as React from 'react';
import Masonry from 'react-masonry-component';

class Gallery extends React.Component {
    handleLayoutComplete() { },

    componentDidMount() {
        this.masonry.on('layoutComplete', this.handleLayoutComplete);
    },

    componentWillUnmount() {
        this.masonry.off('layoutComplete', this.handleLayoutComplete);
    },

     render() {
         return (
             <Masonry
                 ref={function(c) {this.masonry = this.masonry || c.masonry;}.bind(this)}
             >
                 {...}
             </Masonry>
         );
     }
}

export default Gallery;
Images Loaded Options

React Masonry Component uses Desandro's imagesloaded library to detect when images have loaded. Should you want to pass options down to it then you need to populate the imagesLoadedOptions property on React Masonry Component.

This will most commonly be used when the elements in your gallery have CSS background images and you want to capture their load event. More info availabe on the imagesloaded website.

eg:

import * as React from 'react';
import Masonry from 'react-masonry-component';

class Gallery extends React.Component {
  render() {
    const imagesLoadedOptions = { background: '.my-bg-image-el' }
    
    return (
        <Masonry
            className={'my-gallery-class'}
            elementType={'ul'}
            options={masonryOptions}
            imagesLoadedOptions={imagesLoadedOptions}
        >
            <div className="my-bg-image-el"></div>
        </Masonry>
    );
  }
}

export default Gallery;
Events
  • onImagesLoaded - triggered when all images are loaded or after each image is loaded when updateOnEachImageLoad is set to true
  • onLayoutComplete - triggered after a layout and all positioning transitions have completed.
  • onRemoveComplete - triggered after an item element has been removed
class Gallery extends React.Component {
    componentDidMount() {
        this.hide();
    },
    handleImagesLoaded(imagesLoadedInstance) {
        this.show();
    },
    render() {
        return (
            <Masonry
                onImagesLoaded={this.handleImagesLoaded}
                onLayoutComplete={laidOutItems => this.handleLayoutComplete(laidOutItems)}
                onRemoveComplete={removedItems => this.handleRemoveComplete(removedItems)}
            >
                {...}
            </Masonry>
        )
    }
}

react-masonry-component's People

Contributors

a-tokyo avatar adavidaisnoone avatar afram avatar anyab5 avatar b3nj4m avatar baktun14 avatar dazyang avatar donlion avatar duiker101 avatar eiriklv avatar hoschi avatar inxilpro avatar kevinchiu avatar kyleamathews avatar madsleejensen avatar manuege avatar maxkoshel avatar metakermit avatar mgreca avatar mikelambert avatar rasmuskl avatar sarunas avatar tonytonyjan avatar wchaering avatar y310 avatar yoadsn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-masonry-component's Issues

Can you also include the styles, could not get the padding to display right using bootstrap

In the example, you have class name open to customization, would it be possible also to provide those styles as an optional dependency?

           ... // image 
           <li className="image-element-class">

            .... // gallery
            className={'my-gallery-class'} // default ''

I am using bootstrap's thumbnail component, and it is not working for me at all. The functionalities are working, but the styling looks off. For example, there are no padding between each child elements.

    var React = require('react');
    var Masonry = require('react-masonry-component')(React);
    var elements = [{src: "http://placehold.it/350x150"}, {
        src: "http://placehold.it/350x150"
    }, {src: "http://placehold.it/350x150"}, {src: "http://placehold.it/350x150"}, {src: "http://placehold.it/350x150"}];

    var masonryOptions = {
        transitionDuration: 0
    };

    var Gallery = React.createClass({
        render: function () {

            var childElements = this.props.elements.map(function (element) {
                return (
                        <div className="col-xs-6 col-md-4 col-lg-3">
                            <a href="#" className="thumbnail">
                                <img src={element.src} alt="example"/>
                            </a>
                        </div>
                );
            });

            return (
                <Masonry
                    className={'row'} // default ''
                    elementType={'div'} // default 'div'
                    options={masonryOptions} // default {}
                    disableImagesLoaded={false} // default false
                >
                    {childElements}
                </Masonry>
            );
        }
    });

    module.exports = Gallery;

Fork Idea - Infinite scrolling

HI @eiriklv, thanks for the great project. 👍 I have a general question. I need to extend your work to add infinite scrolling. My plan is to fork your work and make my sub-project available to others. I'm pretty new to React and Masonry, so i was wondering if you had any thoughts on how you would solve this problem? Furthermore, are there any infinite scrolling libs that you know of which would be a good fit for integrating with your work? thanks

Styling child elements

I can't figure out what I'm doing wrong. My code below is almost identical to the example given, but I'm trying to style the child elements of the Masonry component. The problem is that transitions don't work with the current styling. If I remove the "height" property and only use "width", transitions do work! Can anyone help? (I'm using the latest Chrome browser.)

import React from 'react';
var Masonry = require('react-masonry-component')(React);

var masonryOptions = {
    transitionDuration: '0.6s',
    columnWidth: 200
};

class Container extends React.Component {

    render() {

        let style = { width: 180, height: 180 };  //**** styling seems to cause trouble 

         let urls = ["../img/worksheet.jpg", "../img/activity.jpg"];

        let childElements = urls.map((url,idx)=>{
            return <img key={idx} style={style} src={url} />;
        });

        return (
            <Masonry
                className={''} // default ''
                elementType={'div'} // default 'div'
                options={masonryOptions} // default {}
                disableImagesLoaded={false} // default false
            >
                {childElements}
            </Masonry>
        )
    }

}

export default Container; 

How do you bind to masonry events?

I'd like to change the state of my app once the masonry layout is complete but that requires binding to the event listener "layoutComplete". Does this component provide an instance to the masonry object for event binding?

Unknown proptypes passed down to elementType node.

Since react v15.2.0, you will get a warning when you pass a prop, that is not in the proptypes, to a DOM node.

Example:

<Masonry
  ref="masonry"
  className={'grid'}
  elementType={'ul'}
  options={masonryOptions}
  disableImagesLoaded={false}>
 {/* Other code */}
</Masonry>

Gives the following warnings:
Warning: Unknown props elementType, options, disableImagesLoaded on ul tag. Remove these props from the element. For details, see https://fb.me/react-unknown-prop

react-masonry-component doesn't respect masonry's initLayout setting

I am trying to handle the call of .layout() myself and looking at masonry's docs one can disable the layout by setting initLayout to false.

However this component doesn't use this option to disable the following lines that trigger layout:

    componentWillReceiveProps: function() {
        this._timer = setTimeout(function() {
            this.masonry.reloadItems();
            this.isMounted && this.isMounted() && this.forceUpdate();
        }.bind(this), 0);
    },

    componentDidUpdate: function() {
        this.performLayout();
        this.imagesLoaded();
    },

masonry-layout 4.0

Hi folks!

I noticed that Masonry 4.x is out, and it seems to me that it cuts file size pretty heavily by not requiring jQuery (don't quote me on that at all...) Is work being done to upgrade? I can possibly help, though I'm not familiar at all with the code base yet.

container div does not resize properly when children are removed

Hi I have a use case that's giving some problems.
I'm putting children inside a div container with a certain height, and has overflow:auto
The component works fine, but when I change the children list to a shorter size, and upon rerender, the container div height would not shrink. It would take 2 state changes for the container div to shrink properly.

Any idea why this is? Thanks

Use

Hello,

I was expecting to use this component like this:

<Gallery>
<img src="" / >
<img src="" / >
<img src="" / >
<img src="" / >
</Gallery>

And I'm getting this error

TypeError: Cannot read property 'map' of undefined
    at Constructor.render (/Users/ricardorauch/Sites/rickyrauch.me/.next/dist/components/gallery.js:21:48)
    at /Users/ricardorauch/Sites/rickyrauch.me/node_modules/react/lib/ReactCompositeComponent.js:793:21
    at measureLifeCyclePerf (/Users/ricardorauch/Sites/rickyrauch.me/node_modules/react/lib/ReactCompositeComponent.js:74:12)

Layout seems to stack up?

Sometimes the masonry layout seems to work when my data is loaded from the server. But sometimes it's just messed. Tried to debug it and couldn't find it.
Can someone help me with this?
I don't know if this is related to this #54

screenshot from 2016-12-26 23-09-32
screenshot from 2016-12-26 23-12-51

Its live here http://bindi.surge.sh/

webpack production build - SyntaxError

I'm no expert and understand that raising this as an issue may not be the correct thing to do, I just cannot get it to work.

The plugin works fine in my dev build process but when trying to compile for production i'm getting this error.

ERROR in bundle.js from UglifyJs
SyntaxError: Unexpected token: name (forceItemReload) [./~/react-masonry-component/lib/index.js:68,0]

The error is coming from UglifyJs so could it be something to do with my webpack config? see below for the uglify plugin configuration that i've been using to minify react.

    new webpack.optimize.UglifyJsPlugin({
      compress: {
        screw_ie8: true
      }
    })

"Bad masonry element"

Hi, I'm instantiating Masonry pretty similarly to how you have it in the example, except each child element is a React component. For some reason, the dependent library outlayer throws an error "Bad masonry element". After that, it repeatedly has a "Can't read property children of undefined" error. Not sure what's going wrong here.

For some more context, I'm using React as the front-end with Meteor as the back-end. Thoughts about where this could be coming from?

Component doesn't update if Children resize

The React-Masonry-Component does not update if a child component changes size - it causing overlapping issues/general ugliness.
There should be a way to monitor children component for size changes.

For example in this scenario. If ChildOne's state is updated it will be re-rendered but the Masonry component would not be and therefore not realigned properly (unless it was listening for the same changes - which is not always practical).

<Masonry options={options}>
   <ChildOne />
   <ChildTwo />
</Masonry 

Am I doing something wrong or is this an actual bug/not fixable?

Cheers!

might be the same issue as #2

Broken rendering when removing elements

I am adding/hiding elements within my component in response to a filter bar (kinda like what Isotope does). Everything works beautifully with animation, except removal of elements at the top of the Masonry layout:

When I have items 1-20 in the Masonry component, and then remove items 1-10, it leaves items 11-20. Unfortunately, instead of laying these out appropriately, it renders them all on the left side of the page (ie, they all have left: 0px).

When I dig into the react-masonry-component code, diffDomChildren seems to work correctly and return proper dictionaries, except when elements are removed. When these elements are removed, diffDomChildren returns:

{
  appended: [],
  moved: [],
  new: [10 elements],
  old: [10 elements],
  prepended: [],
  removed: []
}

(I believe it should be returning 20 'old' elements, with 10 'removed'.)

If I change:

        var oldChildren = this.domChildren.filter(function(element) {
            /*
             * take only elements attached to DOM
             * (aka the parent is the masonry container, not null)
             */
            return !!element.parentNode;
        });

to:

        var oldChildren = this.domChildren;

...then things work beautifully again. I'm confused why my change works, as it obviously seems to be intentionally written the way you've written it. When componentDidUpdate is called, it seems the DOM elements have already been removed from the DOM and had their parentNode null-ed.

I see this behavior with both React 15.1.0 and React 15.4.1 (along with react-masonry-component 4.4.0 and masonry-layout 4.1.1.)

The function componentWillReceiveProps...

The

    componentWillReceiveProps: function() {
        this._timer = setTimeout(function() {
            this.masonry.reloadItems();
            this.isMounted && this.isMounted() && this.forceUpdate();
        }.bind(this), 0);
    },

Is this block really needed as it seems to cause everything to run twice and it seems that I get some minor animation transition problems.

Working in Safari?

Has anyone got this working in safari? I have it working in chrome and firefox, but safari crashes

Masonry only aligns divs correctly after state change

Hi

I'm calculating the container and divs width and height before rendering masonry, but they only arrange correctly on a state change. Initially they're arranged stacked on top of eachother.

Is there any reason for this? Not sure if the fault lies with how I'm using React or Masonry atm.

Console warning: forcedUpdate

Hi,

Thanks for this component! I'm having a slight issue when navigating away from pages using this component, with the console giving me the following warning:

Warning: forceUpdate(...): Can only update a mounted or mounting component. This usually means you called forceUpdate() on an unmounted component. This is a no-op.

How to append/prepend items without re-rendering the whole grid?

In my React application I've set a timer that polls for new posts from a certan API. Whenever a new post is fetched, the component that holds the Masonry component receives the updated array of posts causing the render() method to trigger. This causes the whole grid to be re-rendered (all the items do the animation, instead of just the new ones).

In the old project I used to do that the masonry docs says:

$grid.prepend( $items )
// add and lay out newly prepended items
    .masonry( 'prepended', $items );

How to achieve such behavior with react and react-masonry-component?

I'm new to React so maybe this is not related specifically to your component. I'm sorry if that's the case.

Error occur on IE

return {
old: knownChildrenStillAttached, // Not used
new: currentDomChildren, // Not used
removed: removed,
appended: appended,
prepended: prepended,
moved: moved,
//forceItemReload <- this code occur error on IE (message : ' : ' is required)
forceItemReload:forceItemReload
};

Hearsay.me source

Would be really useful if the original source for the hearsay.me live demo was somehow included here.

masonry instance is not accessible

I've been trying to get a hold of masonry instance after render() by passing masonry via refs like so..

class List extends Component {
  componentDidMount() {
    if (this.masonry) {
      console.log(this.masonry); //  undefined
    }
   else{
     console.log(this); // can see masonry as a SubClass instance
    }
  }

  render() {
    const listItems = [items];
    return (<Masonry
      ref={c => this.masonry = c.masonry}
      className={'my-grid-class'}
      elementType={'ul'}
      options={masonryOptions}
      disableImagesLoaded={false}
      updateOnEachImageLoad={false}
    >
    {listItems}
    </Masonry>);
  }
}

Not sure what I'm missing here. Would be awesome if you can get a chance to help out.
/cc @eiriklv

Why are dependencies linked to Github instead of NPM and semver?

Wondering why this library and most (all?) the libraries it depends on are pulling in Github dependencies?

They currently don't support semver versioning, and this leads to unpredictable results.

For instance this change from 2 days ago in a downstream dependency broke react-masonry-component for us. We had to shrinkwrap to enforce version numbers from within git dependencies.

desandro/matches-selector@7582db4

What are the thoughts on moving dependencies over to npm?

Error if enableResizableChildren is false

Upgrading from 4.2.1 to 4.3.0 and getting the below exception. In my case, enableResizableChildren is false so initializeResizableChildren returns without setting this. erd. When destroyErd is called (from componentWillUnmount) it unconditionally references this.erd resulting in the following error. This is a result of PR #55. All is fine with 4.2.1

TypeError: Cannot read property 'uninstall' of undefined
    at Constructor.destroyErd (index.js:200)
    at Constructor.componentWillUnmount (index.js:215)
    at ReactCompositeComponent.js:408
    at measureLifeCyclePerf (ReactCompositeComponent.js:74)
    at ReactCompositeComponentWrapper.unmountComponent (ReactCompositeComponent.js:407)
    at Object.unmountComponent (ReactReconciler.js:80)
    at ReactCompositeComponentWrapper._updateRenderedComponent (ReactCompositeComponent.js:754)
    at ReactCompositeComponentWrapper._performComponentUpdate (ReactCompositeComponent.js:721)
    at ReactCompositeComponentWrapper.updateComponent (ReactCompositeComponent.js:642)
    at ReactCompositeComponentWrapper.receiveComponent (ReactCompositeComponent.js:544)

Investigate usage in Meteor

It seems that there are issues using this with Meteor. Need to solve the pain points and update component/readme

handleImagesLoaded triggers multiple times

handleImagesLoaded triggers multiple times,
I am using:
onLayoutComplete={handleImagesLoaded}
with function inside the createClass
onLayoutComplete={this.handleImagesLoaded}
it triggers 2 times , otherwise its 4 or 5

Virtual render for big number of items?

Hi, Just wanted to ask if there is a way to use virtual rendering to be able to render a big number of items and implement infinite scrolling...
I use this Masonry component to render "cards" that each contains a small image gallery. it renders great with a small number of items, but with a few hundreds it gets clunky...
is there a virtual rendering at all to ensure only the part of the least being rendered is the part that consumes memory while all the rest is free from it?
Cheers
Ajar

Problem left position 0

Hello,
I try to implement your react component in a project but the margin left is all the time equal to 0.

My React compoment :

import React from 'react';
import ReactDOM from 'react-dom';
import Masonry from 'react-masonry-component';
import { default as Video, Controls, Play, Mute, Seek, Fullscreen, Time, Overlay } from 'react-html5video';


var masonryOptions = {
    itemSelector: '.grid-item',
    columnWidth: '.grid-sizer',
    gutter: 10,
    isOriginLeft: true
};

export class Gallery extends React.Component {

    constructor()
    {
        super();
        this.state = {
            elements: []
        };
    };

    componentDidMount()
    {
        $.ajax({
            url: this.props.url,
            dataType: 'json',
            cache: false,
            success: function(data) {
                this.setState({
                    elements: data.contents
                });
            }.bind(this),
            error: function(xhr, status, err) {
                alert("Erreur lors de la requête code : " + status + err.toString());  
            }.bind(this)
        });
    };

    render() 
    {
        var childElements = this.state.elements.map(function(element, index) {
            if(element.type === 'images') {
                return (
                    <li className='grid-item'>
                        <img src={element.src} />
                    </li>    
                );
            }

            if(element.type === 'video') {
                return(
                    <li className='grid-item'>
                        <Video controls
                            poster="https://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&cad=rja&uact=8&ved=0ahUKEwjP54jK4IHOAhUE1RoKHXpABMwQjRwIBw&url=http%3A%2F%2Fwww.izoa.fr%2Fpapier-peint-deco-paysage%2F2729-poster-mural-design-tokyo-by-night.html&bvm=bv.127521224,d.d2s&psig=AFQjCNHVqrk-6MpdtGRLCJCsI4AMZOhrug&ust=1469094218037889"
                            onCanPlayThrough={() => {

                            }}>
                            <source src={element.src} type="video/mp4" />
                        </Video>
                    </li>
                );
            }
        });

        return (
            <Masonry
                className={'grid'} // default ''
                elementType={'gridMasonry'} // default 'div'
                options={masonryOptions} // default {}
                disableImagesLoaded={false} // default false
                updateOnEachImageLoad={false} // default false and works only if disableImagesLoaded is false
            >
            <div className="grid-sizer"></div> 
                {childElements}
            </Masonry>
        );
    };
}

My html file :

<!doctype html>
<html>
    <head>
        <link rel="stylesheet" type="text/css" href="src/css/style.css">
    </head>
    <body>
        <h1> Test React Masonry </h1>
        <div id="gridMasonry">


        </div>
    </body>
    <script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
    <script type="text/javascript" src="bundle.js">  </script>
    <script type="text/javascript" src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
</html>

The css :

/* ---- grid ---- */
.grid {
    max-width: 100%;
    padding: 0;    
}
/* ---- grid-item ---- */
.grid-sizer{
    width: calc(33% - 5px);
}
.grid-item {
    float: left;
}

#gridMasonry {
    height: 600px;
    width: 700px;
}

The main js

import {Gallery} from './gallery.jsx';
import ReactDOM from 'react-dom';
import React from 'react';


ReactDOM.render(<Gallery url="http://localhost/projetReactMasonry/json.php"/>, document.getElementById('gridMasonry'));

Have you got any ideas for this problem ?

The objective is to render images/movies from a json call with a path.

Thank you for future answer,
Julien

Notes on using webpack in the readme

Are the Usage with webpack instructions in the README still applicable. I use webpack, I didn't install/configure the imports-loader and everything works fine. To the contrary... if I install and configure the imports-loader per the instructions webpack stops working. I'm asking in case I'm overlooking something important.

Elements are in wrong position on a 're-render' caused by unfiltering a filtered array

I am displaying my masonry tiles from a filtered array.

var myFilteredArray = myArray.filter( (tile) => this.props.filter.indexOf(tile.tag) > -1 )
var tiles = myFilteredArray.map( (tile) => <MyTile/>) 

Where myArray is an array of json objects with a tag field. props.filter is an array of strings.

For exampleprops.filter = ["a","b","c"] and the json tags are "a", "b", "c"

When I update my props filter so that props.filter = ["b"]

I see that the A and C objects disappear and object B moves to the left most of the container.

However when I add back tags "a" and "c" into props.filter, the objects show up in the wrong position.
I would expect that the objects be in the order A,B,C, and filling up the container from the left most. What I see however is that object B goes back to where it was originally, and A, and C show up either on top of it or to the right of is. That means there is a big empty space to the left of Object B

My question is why is this happening? And how do I fix this?

Preserve children order?

Is there any way to prevent masonry from re-ordering elements? I don't need the "optimal" placement of elements as the order of my elements is important. All I want is for 2 elements in the same column to have no whitespace between them.

ES6 & Typescript

Hi, I've been struggling to make the events work with typescript. I followed the example you gave but it just never fires. Maybe I'm doing something wrong, i don't know, I'm quite new to react and typescript/es6. Would be cool if you could provide a complete example!

Here's a small portion of the code

Thanks

var Masonry = require('react-masonry-component');

public handleImagesLoaded(imagesLoadedInstance) {
    this.setState({
      showImages: true
    });
  }

public render() {
    let masonryOptions = {
      transitionDuration: 0
    };

    let posts = this.state.showImages ? this.state.posts.map((post, i) => {
      return <PostComponentReact key={i} post={post}></PostComponentReact>
    }) : null;

    return (
      <section id="content">
        <div className="page pl-25 pr-25 mb-40">
          <Masonry className="row"
            ref="masonry"
            options={masonryOptions}
            onImagesLoaded={this.handleImagesLoaded}
            >

            {posts}

          </Masonry>
        </div>
      </section>
    )
  }

TypeError: Cannot read property 'bool' of undefined

I get this error when trying to include the masonry component:

TypeError: Cannot read property 'bool' of undefined
at new MasonryComponent (/Users/pvijeh/projects/sull-isom/node_modules/react-masonry-component/lib/index.js:15:49)
at [object Object].ReactCompositeComponentMixin.mountComponent (/Users/pvijeh/projects/sull-isom/node_modules/react/lib/ReactCompositeComponent.js:148:18)
at [object Object].wrapper as mountComponent
at Object.ReactReconciler.mountComponent (/Users/pvijeh/projects/sull-isom/node_modules/react/lib/ReactReconciler.js:37:35)
at [object Object].ReactCompositeComponentMixin.mountComponent (/Users/pvijeh/projects/sull-isom/node_modules/react/lib/ReactCompositeComponent.js:225:34)
at [object Object].wrapper as mountComponent
at Object.ReactReconciler.mountComponent (/Users/pvijeh/projects/sull-isom/node_modules/react/lib/ReactReconciler.js:37:35)
at [object Object].ReactCompositeComponentMixin.mountComponent (/Users/pvijeh/projects/sull-isom/node_modules/react/lib/ReactCompositeComponent.js:225:34)
at [object Object].wrapper as mountComponent
at Object.ReactReconciler.mountComponent (/Users/pvijeh/projects/sull-isom/node_modules/react/lib/ReactReconciler.js:37:35)
at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (/Users/pvijeh/projects/sull-isom/node_modules/react/lib/ReactMultiChild.js:241:44)
at ReactDOMComponent.Mixin._createContentMarkup (/Users/pvijeh/projects/sull-isom/node_modules/react/lib/ReactDOMComponent.js:591:32)
at ReactDOMComponent.Mixin.mountComponent (/Users/pvijeh/projects/sull-isom/node_modules/react/lib/ReactDOMComponent.js:479:29)
at Object.ReactReconciler.mountComponent (/Users/pvijeh/projects/sull-isom/node_modules/react/lib/ReactReconciler.js:37:35)
at [object Object].ReactCompositeComponentMixin.mountComponent (/Users/pvijeh/projects/sull-isom/node_modules/react/lib/ReactCompositeComponent.js:225:34)
at [object Object].wrapper as mountComponent

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Here is my webpack config file:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**

  • React Starter Kit (http://www.reactstarterkit.com/)
    *
  • Copyright © 2014-2015 Kriasoft, LLC. All rights reserved.
    *
  • This source code is licensed under the MIT license found in the
  • LICENSE.txt file in the root directory of this source tree.
    */

import path from 'path';
import webpack from 'webpack';
import merge from 'lodash.merge';

const DEBUG = !process.argv.includes('--release');
const VERBOSE = process.argv.includes('--verbose');
const WATCH = global.WATCH === undefined ? false : global.WATCH;
const AUTOPREFIXER_BROWSERS = [
'Android 2.3',
'Android >= 4',
'Chrome >= 35',
'Firefox >= 31',
'Explorer >= 9',
'iOS >= 7',
'Opera >= 12',
'Safari >= 7.1',
];
const GLOBALS = {
'process.env.NODE_ENV': DEBUG ? '"development"' : '"production"',
DEV: DEBUG,
};

//
// Common configuration chunk to be used for both
// client-side (app.js) and server-side (server.js) bundles
// -----------------------------------------------------------------------------

const config = {
output: {
publicPath: '/',
sourcePrefix: ' ',
},

cache: DEBUG,
debug: DEBUG,

stats: {
colors: true,
reasons: DEBUG,
hash: VERBOSE,
version: VERBOSE,
timings: true,
chunks: VERBOSE,
chunkModules: VERBOSE,
cached: VERBOSE,
cachedAssets: VERBOSE,
},

plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
],

resolve: {
extensions: ['', '.webpack.js', '.web.js', '.js', '.jsx', '.json'],
},

module: {
loaders: [
{
test: /.jsx?$/,
include: [
path.resolve(__dirname, '../node_modules/react-routing/src'),
path.resolve(__dirname, '../src'),
],
loader: 'babel-loader',
}, {
test: /.json$/,
loader: 'json-loader',
}, {
test: /.txt$/,
loader: 'raw-loader',
}, {
test: /.(png|jpg|jpeg|gif|svg|woff|woff2)$/,
loader: 'url-loader?limit=10000',
}, {
test: /.(eot|ttf|wav|mp3)$/,
loader: 'file-loader',
}, {
test: /.scss$/,
loader: 'style-loader/useable!css-loader!postcss-loader',
}, {
test: /.jsx?$/,
exclude: /node_modules/,
loader: 'babel'
},
{
test: /masonry|imagesloaded|fizzy-ui-utils|desandro-|outlayer|get-size|doc-ready|eventie|eventemitter/,
loader: 'imports?define=>false&this=>window'
}
],
},

postcss: function plugins(bundler) {
return [
require('postcss-import')({ addDependencyTo: bundler }),
require('precss')(),
require('autoprefixer')({ browsers: AUTOPREFIXER_BROWSERS }),
require('css-mqpacker')(),
require('csswring')()
// require('cssnano')({discardComments: {removeAll: true}})
];
},
};

//
// Configuration for the client-side bundle (app.js)
// -----------------------------------------------------------------------------

const appConfig = merge({}, config, {
entry: [
...(WATCH ? ['webpack-hot-middleware/client'] : []),
'./src/app.js',
],
output: {
path: path.join(__dirname, '../build/public'),
filename: 'app.js',
},

// Choose a developer tool to enhance debugging
// http://webpack.github.io/docs/configuration.html#devtool
devtool: DEBUG ? 'cheap-module-eval-source-map' : false,
plugins: [
new webpack.DefinePlugin(GLOBALS),
...(!DEBUG ? [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: VERBOSE,
},
}),
new webpack.optimize.AggressiveMergingPlugin(),
] : []),
...(WATCH ? [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
] : []),
],
});

// Enable React Transform in the "watch" mode
appConfig.module.loaders
.filter(x => WATCH && x.loader === 'babel-loader')
.forEach(x => x.query = {
// Wraps all React components into arbitrary transforms
// https://github.com/gaearon/babel-plugin-react-transform
plugins: ['react-transform'],
extra: {
'react-transform': {
transforms: [
{
transform: 'react-transform-hmr',
imports: ['react'],
locals: ['module'],
}, {
transform: 'react-transform-catch-errors',
imports: ['react', 'redbox-react'],
},
],
},
},
});

//
// Configuration for the server-side bundle (server.js)
// -----------------------------------------------------------------------------

const serverConfig = merge({}, config, {
entry: './src/server.js',
output: {
path: './build',
filename: 'server.js',
libraryTarget: 'commonjs2',
},
target: 'node',
externals: [
function filter(context, request, cb) {
const isExternal =
request.match(/^[@a-z][a-z/.-0-9]*$/i) &&
!request.match(/^react-routing/) &&
!context.match(/[/]react-routing/);
cb(null, Boolean(isExternal));
},
],
node: {
console: false,
global: false,
process: false,
Buffer: false,
__filename: false,
__dirname: false,
},
devtool: 'source-map',
plugins: [
new webpack.DefinePlugin(GLOBALS),
new webpack.BannerPlugin('require("source-map-support").install();',
{ raw: true, entryOnly: false }),
],
});

// Remove style-loader from the server-side bundle configuration
serverConfig.module.loaders
.filter(x => x.loader.startsWith('style-loader/useable!'))
.forEach(x => x.loader = x.loader.substr(21));

export default [appConfig, serverConfig];

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Here is my package.json file:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

{
"private": true,
"engines": {
"node": ">=4.1 <5",
"npm": ">=3.1 <4"
},
"dependencies": {
"babel-core": "5.8.33",
"bluebird": "3.0.5",
"classnames": "2.2.0",
"eventemitter3": "1.1.1",
"exenv": "^1.2.0",
"express": "4.13.3",
"fastclick": "1.0.6",
"fbjs": "0.4.0",
"flux": "2.1.1",
"front-matter": "2.0.0",
"history": "1.13.1",
"imports-loader": "^0.6.5",
"jade": "1.11.0",
"jquery": "^2.1.4",
"lodash": "^3.10.1",
"normalize.css": "3.0.3",
"object-assign": "^4.0.1",
"postcss-mixins": "^3.0.2",
"react": "0.14.2",
"react-dom": "0.14.2",
"react-routing": "0.0.5",
"source-map-support": "0.3.3",
"superagent": "1.4.0"
},
"devDependencies": {
"autoprefixer": "^6.1.0",
"babel": "^5.8.34",
"babel-eslint": "^4.1.4",
"babel-loader": "^5.3.3",
"babel-plugin-react-transform": "^1.1.1",
"browser-sync": "^2.9.12",
"css-loader": "^0.23.0",
"css-mqpacker": "^4.0.0",
"csscomb": "^3.1.8",
"csswring": "^4.0.0",
"del": "^2.0.2",
"eslint": "^1.8.0",
"eslint-config-airbnb": "1.0.0",
"eslint-loader": "^1.1.1",
"eslint-plugin-react": "^3.7.1",
"file-loader": "^0.8.4",
"gaze": "^0.5.2",
"git-repository": "^0.1.1",
"glob": "^6.0.1",
"jest-cli": "^0.7.1",
"jscs": "^2.5.0",
"lodash.merge": "^3.3.2",
"mkdirp": "^0.5.1",
"ncp": "^2.0.0",
"postcss": "^5.0.10",
"postcss-import": "^7.1.3",
"postcss-loader": "^0.8.0",
"precss": "^1.3.0",
"react-transform-catch-errors": "^1.0.0",
"react-transform-hmr": "^1.0.1",
"redbox-react": "^1.1.1",
"replace": "^0.3.0",
"style-loader": "^0.13.0",
"url-loader": "^0.5.6",
"webpack": "^1.12.3",
"webpack-dev-middleware": "^1.2.0",
"webpack-hot-middleware": "^2.5.0"
},
"jest": {
"rootDir": "./src",
"scriptPreprocessor": "../preprocessor.js",
"unmockedModulePathPatterns": [
"fbjs",
"react"
]
},
"scripts": {
"lint": "eslint src tools && jscs src tools",
"csslint": "csscomb src/components --lint --verbose",
"csscomb": "csscomb src/components --verbose",
"test": "eslint src && jest",
"clean": "babel-node tools/run clean",
"copy": "babel-node tools/run copy",
"bundle": "babel-node tools/run bundle",
"build": "babel-node tools/run build",
"deploy": "babel-node tools/run deploy",
"serve": "babel-node tools/run serve",
"start": "babel-node tools/run start"
}

Performance issues

I have 12 objects in my Masonry container. Upon changing one of the objects, the entire masonry component must update.

However I'm seeing quite a significant jank as a result. When I use an ordinary container instead of a Masonry container the jank does not occur.

Any reasons why? In my 12 objects I return false in shouldComponentUpdate for 11 of them so I know only 1 rerenders, and the masonry rerenders, but I don't understand the jank that Masony is causing.

Any suggestions what may be the cause?

Will not compile with TypeScript

With

import * as Masonry from 'react-masonry-component';

I get

ERROR in /media/website/js/node_modules/react-masonry-component/typings.d.ts
(5,22): error TS2665: Module augmentation cannot introduce new names in the top level scope.

ERROR in /media/website/js/node_modules/react-masonry-component/typings.d.ts
(20,15): error TS2665: Module augmentation cannot introduce new names in the top level scope.

ERROR in /media/website/js/node_modules/react-masonry-component/typings.d.ts
(29,26): error TS2665: Module augmentation cannot introduce new names in the top level scope.

"typescript": "^1.8.10"
"react-masonry-component": "^4.2.0"

EDIT: I see this could be a duplicate of #42

Bad position/placement if element is prepended in array

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;

Broken image

Hi. Is anyone know how to detect broken image? not anyBroken, i want to check each image on load for know is it loaded, broken, and create some placeholder for image, and then when image is loaded === true, change placeholder to loaded image or to broken placeholder.

disableImagesLoaded not parsing boolean value

Hi guys,

Having an issue with Masonry Component's parameter "disableImagesLoaded". It throws this error:

Uncaught TypeError: Cannot read property 'bool' of undefined

I've tried parsing false and creating a variable with false, but doesn't seem to work.

Is anyone else having issues with this?

React 0.14 compatibility

Hi Eirik, thanks for building this. When using with React 0.14 RC1:

If using React.render(), the app works fine, but I get:

Warning: React.render is deprecated. Please use ReactDOM.render from require('react-dom') instead.
Warning: React.findDOMNode is deprecated. Please use ReactDOM.findDOMNode from require('react-dom') instead.

If importing ReactDOM and using ReactDOM.render(), the app does not work, I get:

Uncaught (in promise) Error: Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).

Add Travis CI

@eiriklv Firstly what do you think about adding Travis CI support in order to run tests on commit/pull request?

Second, you will have to do it, the repo is under your account.

(We could also create an org for this, but that might be overkill)

Unknown prop warning

Updated React today to be greeted with this warning in the console. Haven't changed anything from my masonry component, still trying to figure out exactly how to prevent it. Only Masonry triggering this warning. My code is standard from README.md.

image

Linked: https://fb.me/react-unknown-prop

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.