React.js and Isotope.js
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();
}
}
});
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.