I am working on an isotope application - and I want to smooth this application so that onclick an item expands -- but on clicking another item - it closes the last -- here is the code base - what is the best way of handling this. My problem at the moment is its possible to open up multiple cells at once - and I haven't worked out the logic to collapse non-active items.
https://codesandbox.io/s/brave-sea-tnih7?file=/src/IsotopePopClickEl.js
IsotopePopClickEl.
import React, { Component } from "react";
import Grid from "@material-ui/core/Grid";
import Button from "@material-ui/core/Button";
//import Rating from '@material-ui/lab/Rating';
//import parse from 'html-react-parser';
import "./IsotopePopClickEl.css";
class IsotopePopClickEl extends Component {
constructor(props, context) {
super(props, context);
this.state = { expanded: false };
this.onClick = this.onClick.bind(this);
}
expand() {
this.setState({
expanded: true
});
}
collapse(event) {
this.setState({
expanded: false
});
}
onClick() {
if (this.state.expanded) {
this.collapse();
} else {
this.expand();
}
}
render() {
return (
<div
className={
"isotope-pop-click " +
(this.state.expanded ? "is-expanded" : "is-collapsed")
}
onClick={this.onClick}
>
<div className="frontFace">
<Grid container spacing={0}>
<Grid item xs={12} sm={12}>
<div className="image-wrapper">
<img
className="image-item"
src={this.props.item.image}
alt=""
/>
</div>
<h3>{this.props.item.label}</h3>
</Grid>
</Grid>
</div>
<div className="backFace">
<Grid container spacing={0}>
<Grid item xs={12} sm={5}>
<div className="image-wrapper">
<img
className="image-item"
src={this.props.item.image}
alt=""
/>
</div>
</Grid>
<Grid item xs={12} sm={7}>
<h3>{this.props.item.label}</h3>
<div>
<p>some body text text text text</p>
</div>
<div>
<Button variant="contained" color="primary">
Read more
</Button>
</div>
</Grid>
</Grid>
</div>
</div>
);
}
}
export default IsotopePopClickEl;
I wasn't sure what is the easier way to handle this -- if its a case of pushing back an active item record into the parent shell IsotopeWrapper - and if a new click is picked up to close all other IsotopePopClickEl's --
I have to make bunch of changed to your codesandbox as there are few issues with existing code. Updated and working codesandbox can be found here.
Let's go through the changes I made:
state
from IsotopePopClickEl
and moved it to IsotopeWrapper
where wrapper would set selected
property on each item to indicate if it is selected (or you can call it expanded!) or not.class IsotopePopClickEl extends Component {
...
onClick() {
this.props.onClick();
}
render() {
return (
<div
className={
"isotope-pop-click " +
(this.props.item.selected ? "is-expanded" : "is-collapsed")
}
onClick={this.onClick}
>
...
);
}
}
IsotopePopClickEl
can determine which item to expand to:class IsotopeWrapper extends Component {
constructor(props, context) {
super(props, context);
this.state = {
resultsList: [
// items in the list
]
};
}
onClick(item) {
const newList = this.state.resultsList.map((i) => {
i.selected = i === item;
return i;
});
this.setState({
resultsList: newList
});
}
render() {
let items = [
{
buildEntity: () => ( // <- converted entity prop to method
<IsotopePopClickEl
item={this.state.resultsList[0]} // <- use item from the state
onClick={() => this.onClick(this.state.resultsList[0])} // <- attach click handler
/>
),
...
}
...
}
}
entity
property on each item in IsotopeWrapper
class with buildEntity
function as using property would cache view after creating it for the first time and will not update after wards on new state. Update IsotopeHandler
to call buildEntity
.<div className="grid-item-wrapper">{item.buildEntity()}</div>
That's all!