Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React.js and Isotope.js

I'm checking out React.js and trying to figure out how this library can work together with Isotope.js. The documentation of React says that it plays nicely with other libraries, but using it with library that changes DOM on its own seems like no sense of using React.

Can someone explain to me, how can I take advantage of React in my webapp that uses Isotope.js as layout ?

like image 283
user1091733 Avatar asked Aug 05 '14 09:08

user1091733


People also ask

How do you use isotope JS in React JS?

As React work with diffs, it kind of assumes that it is alone modyfing the dom. With this you can: Use React to generate your isotope item html elements (you can also create them without React) On componentDidMount , initialize isotope on the dom node mounted by React.

Is React JS different from JavaScript?

React is just JavaScript, there is a very small API to learn, just a few functions and how to use them. After that, your JavaScript skills are what make you a better React developer. There are no barriers to entry. A JavaScript developer can become a productive React developer in a few hours.

Can we use JS in React JS?

It is called JSX, and it is a syntax extension to JavaScript. We recommend using it with React to describe what the UI should look like. JSX may remind you of a template language, but it comes with the full power of JavaScript. JSX produces React “elements”.


2 Answers

Here's a working version with Masonry, you should find it easy enough to port to Isotope (or use Masonry :)) http://jsfiddle.net/emy7x0dc/1/.

Here's the crux of the code that makes it work (and allow React to do its job).

var Grid = React.createClass({
    displayName: 'Grid',

    getInitialState: function(){
        return {
            masonry: null
        }
    },

    // Wrapper to layout child elements passed in
    render: function () {
        var children = this.props.children;
        return (
            <div className="grid">
                {children}
            </div>
        );
    },

    // When the DOM is rendered, let Masonry know what's changed
    componentDidUpdate: function() {
        if(this.state.masonry) {
            this.state.masonry.reloadItems();
            this.state.masonry.layout();
        }
    },

    // Set up Masonry
    componentDidMount: function() {
        var container = this.getDOMNode();
        if(!this.state.masonry) {
            this.setState({
                masonry: new Masonry( container )
            });
        } else {
            this.state.masonry.reloadItems();
        }
    }
});
like image 54
James Broad Avatar answered Sep 19 '22 09:09

James Broad


My solution with useRef, useState and useEffect hooks. It also works with dynamically generated filter keys and items. The trick is to initialize Isotope after the component is mounted and call its "arrange" method every time the filter keyword changes.

Demo: https://codepen.io/ilovepku/pen/zYYKaYy

const IsotopeReact = () => {
  // init one ref to store the future isotope object
  const isotope = React.useRef()
  // store the filter keyword in a state
  const [filterKey, setFilterKey] = React.useState('*')

  // initialize an Isotope object with configs
  React.useEffect(() => {
    isotope.current = new Isotope('.filter-container', {
      itemSelector: '.filter-item',
      layoutMode: 'fitRows',
    })
    // cleanup
    return () => isotope.current.destroy()
  }, [])

  // handling filter key change
  React.useEffect(() => {
    filterKey === '*'
      ? isotope.current.arrange({filter: `*`})
      : isotope.current.arrange({filter: `.${filterKey}`})
  }, [filterKey])

  const handleFilterKeyChange = key => () => setFilterKey(key)

  return (
    <>
      <ul>
        <li onClick={handleFilterKeyChange('*')}>Show Both</li>
        <li onClick={handleFilterKeyChange('vege')}>Show Veges</li>
        <li onClick={handleFilterKeyChange('fruit')}>Show Fruits</li>
      </ul>
      <hr />
      <ul className="filter-container">
        <div className="filter-item vege">
          <span>Cucumber</span>
        </div>
        <div className="filter-item fruit">
          <span>Apple</span>
        </div>
        <div className="filter-item fruit">
          <span>Orange</span>
        </div>
        <div className="filter-item fruit vege">
          <span>Tomato</span>
        </div>
      </ul>
    </>
  )
}

UPDATE (17/11/21):

TypeScript Demo: https://codesandbox.io/s/react-isotope-typescript-i9x5v

Don't forget to also add @types/isotope-layout as a dev dependency.

like image 35
Sean Lee Avatar answered Sep 21 '22 09:09

Sean Lee