0

I have created a grid with some images and want to update the number of columns on certain widths. For example:

  • width > 960px: 3 columns
  • width > 660px: 2 columns
  • width < 660px: 1 column

I've created a function to update the number of rows, but how can I rerender the grid without pressing F5?

My states:

this.state = {
  numberOfColumns: 3,
  breakpointSm: 660px,
  breakpointMd: 960px,
};

My function:

getNumberOfColumns(){
  let smallDevices = window.matchMedia( "(max-width: " + this.state.breakpointSm + ")" );
  let mediumDevices = window.matchMedia( "(max-width:" + this.state.breakpointMd + ")" );
  let columns;

  if (smallDevices.matches) {
    columns = 1;
  } else if (mediumDevices.matches){
    columns = 2;
  } else {
    columns = 3;
  }
  this.setState({
    numberOfColumns: columns
  });
}

Component will mount:

componentWillMount() {
  this.getNumberOfColumns();
}
3
  • Why not do this entirely in css? Commented Mar 15, 2018 at 21:11
  • Do it simple w3schools.com/css/css_grid.asp or developer.mozilla.org/es/docs/Web/CSS/CSS_Grid_Layout Commented Mar 15, 2018 at 21:12
  • I've create a masonry grid layout with flexbox. Therefore I've to set the height of the container. I've created a function to calculate the height of the container (height of the items * number of rows). Thats the reason why I can't use plain css. Commented Mar 15, 2018 at 21:32

2 Answers 2

2

a simple way to slove the issue is to added an event listner on resize or simply use a plain css what this code actually do is to force a re-render every time the window size change

    getNumberOfColumns() {
        let columns;
        if(window.innerWidth === this.state.breakpointSm) {
          columns = 1;
        } else if(window.innerWidth === this.state.breakpointMd) {
         columns = 2;

        }else{
       columns = 3;
             }
         this.setState({
             numberOfColumns: columns
                    });
      }


componentDidMount() {
  this.getNumberOfColumns();
window.addEventListener("resize", this.getNumberOfColumns.bind(this));
}

 componentWillUnmount() {
    window.removeEventListener("resize", this.getNumberOfColumns.bind(this));
  }

and in the worst case scenario if nothing work , you can use this.forceUpdate() but try to avoid it as much as you can

i didnt test it yet , but i hope this will help

Sign up to request clarification or add additional context in comments.

6 Comments

.bind(this) creates a new function
if he dont use .bind(this) , it will create a bug and on the componentWillunmount will remove the original event listner , a known pattern to slove the issue in react is to create a new instance of the function
It doesn't work.. I've still to press F5 to refresh the page
window.addEventListener("resize", this.getNumberOfColumns.bind(this)); will add the eventListener to a fn1 and window.removeEventListener("resize", this.getNumberOfColumns.bind(this)); will remove the eventListener to fn2 gist.github.com/Restuta/e400a555ba24daa396cc
store this somewhere let fn1= this.getNumberOfColumns.bind(this) then add do window.addEventListener("resize", fn1); and window.removeEventListener("resize", fn1);
|
1

I would advice using CSS for it, it approach seems more approprate for me. Re-rendering component to do something that can be achieved with media queries in CSS is an overkill IMHO.

CSS:

//for medium screens
.container {
    display: grid;
    grid-template-rows: 1fr 1fr;
    grid-template-columns: auto;
    //for tiny screens
    @media screen and (max-width: 660px) {
        grid-template-rows: 1fr;
    }
    //for big screens
    @media screen and (min-width: 960px) {
        grid-template-rows: 1fr 1fr 1fr;
   }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.