ajmajmajma ajmajmajma - 1 month ago 21
Javascript Question

React, responsive bootstrap rows and cols

I have a react component that maps over some data and displays rows of products. I made a mapping function that also chunks the data upfront based upon the screen size, so everything will fit into a row and there is no weird behavior with the floats and products being slightly different sizes. Here is what I have now:

renderProducts() {
if (this.props.display && this.props.display.productList && this.props.display.productList.hits) {
const chunkedProducts = chunkProductsForWindow(this.props.display.productList.hits);

return chunkedProducts.map((row) => (
<div className="row">
{
row.map((product, index) => (
<div className="col-xs-12 col-sm-6 col-md-3" key={index}>
<h2>{product.product_name}</h2>
<i>{product.product_name}</i>
<p>${product.price}</p>
<Link to={`/product/${product.product_id}`}>details</Link>
</div>
))
}
</div>
));
}
return null;
}


And the chunk function looks like so :

function chunkProductsForWindow(products) {
let chunkSize;
const windowSize = window.innerWidth;

if (windowSize >= 992) {
chunkSize = 4;
} else if (windowSize < 992 && windowSize >= 768) {
chunkSize = 2;
} else {
chunkSize = 1;
}

return _.chunk(products, chunkSize);
}


So, this works fine for me when the page loads. it gets weird when you drag the page around because nothing is re-calculating the chunk size when the user changes the screen size. I am trying to avoid putting a listener on the window size, so what I am wondering is - is there a better way to do this where the wrapping rows would change based on the screen size - the simpler the better.

There are no renders called when the screen size is just being dragged around so I don't think I can tap into react lifecycle events. Wondering if there is a more elegant solution that doesn't require screen size listeners (trying to keep this app as performant as possible). Thanks for reading!

EDIT - added code pen for clarity - https://codepen.io/ajmajma/pen/RGmRXE

For example, start the window small (refresh the page if you need so it reads the initial chunk size as 1), then drag it to large sizes, you will see the products remain in single rows.

Answer

Yes you have to listen to window resize to trigger recalculation and re-render. I would put chuckSize as a component state. But dont call setState on every window resize callback. Instead only call setState when you reach the breakpoints. And you can make window resize callback throttle to increase the performance.

Edit This answer got accepted because of one of the comments below. I copy paste that to avoid confusions...

But in your case your chunkProductsForWindow function and bootstrap grid are doing the same thing. Having both makes it non responsive. You can remove chunkProductsForWindow and just let grid do its job. codepen codepen.io/anon/pen/dpEOoy