HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptreactCritical

Rerender view on browser resize with React

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
viewresizererenderreactwithbrowser

Problem

How can I get React to re-render the view when the browser window is resized?

Background

I have some blocks that I want to layout individually on the page, however I also want them to update when the browser window changes. The very end result will be something like Ben Holland's Pinterest layout, but written using React not just jQuery. I’m still a way off.

Code

Here’s my app:

var MyApp = React.createClass({
  //does the http get from the server
  loadBlocksFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      mimeType: 'textPlain',
      success: function(data) {
        this.setState({data: data.events});
      }.bind(this)
    });
  },
  getInitialState: function() {
    return {data: []};
  },
  componentWillMount: function() {
    this.loadBlocksFromServer();

  },    
  render: function() {
    return (
        
      
      
    );
  }
});

React.renderComponent(
  ,
  document.getElementById('view')
)


Then I have the Block component (equivalent to a Pin in the above Pinterest example):

var Block = React.createClass({
  render: function() {
    return (
        
        {this.props.title}
        {this.props.children}
        
    );
  }
});


and the list/collection of Blocks:

var Blocks = React.createClass({

  render: function() {

    //I've temporarily got code that assigns a random position
    //See inside the function below...

    var blockNodes = this.props.data.map(function (block) {   
      //temporary random position
      var topOffset = Math.random() * $(window).width() + 'px'; 
      var leftOffset = Math.random() * $(window).height() + 'px'; 
      return {block.description};
    });

    return (
        {blockNodes}
    );
  }
});


Question

Should I add jQuery’s window resize? If so, where?

$( window ).resize(function() {
  // re-render the component
});


Is there a more “React” way of doing this?

Solution

Using React Hooks:

You can define a custom Hook that listens to the window resize event, something like this:

import React, { useLayoutEffect, useState } from 'react';

function useWindowSize() {
  const [size, setSize] = useState([0, 0]);
  useLayoutEffect(() => {
    function updateSize() {
      setSize([window.innerWidth, window.innerHeight]);
    }
    window.addEventListener('resize', updateSize);
    updateSize();
    return () => window.removeEventListener('resize', updateSize);
  }, []);
  return size;
}

function ShowWindowDimensions(props) {
  const [width, height] = useWindowSize();
  return Window size: {width} x {height};
}


The advantage here is the logic is encapsulated, and you can use this Hook anywhere you want to use the window size.

Using React classes:

You can listen in componentDidMount, something like this component which just displays the window dimensions (like Window size: 1024 x 768):

import React from 'react';

class ShowWindowDimensions extends React.Component {
  state = { width: 0, height: 0 };
  render() {
    return Window size: {this.state.width} x {this.state.height};
  }
  updateDimensions = () => {
    this.setState({ width: window.innerWidth, height: window.innerHeight });
  };
  componentDidMount() {
    window.addEventListener('resize', this.updateDimensions);
  }
  componentWillUnmount() {
    window.removeEventListener('resize', this.updateDimensions);
  }
}

Code Snippets

import React, { useLayoutEffect, useState } from 'react';

function useWindowSize() {
  const [size, setSize] = useState([0, 0]);
  useLayoutEffect(() => {
    function updateSize() {
      setSize([window.innerWidth, window.innerHeight]);
    }
    window.addEventListener('resize', updateSize);
    updateSize();
    return () => window.removeEventListener('resize', updateSize);
  }, []);
  return size;
}

function ShowWindowDimensions(props) {
  const [width, height] = useWindowSize();
  return <span>Window size: {width} x {height}</span>;
}
import React from 'react';

class ShowWindowDimensions extends React.Component {
  state = { width: 0, height: 0 };
  render() {
    return <span>Window size: {this.state.width} x {this.state.height}</span>;
  }
  updateDimensions = () => {
    this.setState({ width: window.innerWidth, height: window.innerHeight });
  };
  componentDidMount() {
    window.addEventListener('resize', this.updateDimensions);
  }
  componentWillUnmount() {
    window.removeEventListener('resize', this.updateDimensions);
  }
}

Context

Stack Overflow Q#19014250, score: 916

Revisions (0)

No revisions yet.