DraganS DraganS - 18 days ago 7
React JSX Question

React Isomorphic Rendering - handle window resize event

I would like to set the state of a component based on the current size of the browser window. The server-side rendering has been used (React+Redux). I was thinking about using the Redux store as a glue - just to update the store on resize.
Is there any other/better solution that doesn't involve Redux.
Thanks.

class FocalImage extends Component {

// won't work - the backend rendering is used
// componentDidMount() {
// window.addEventListener(...);
//}

//componentWillUnmount() {
// window.removeEventListener('resize' ....);
//}

onresize(e) {
//
}

render() {
const {src, className, nativeWidth, nativeHeight} = this.props;
return (
<div className={cn(className, s.focalImage)}>
<div className={s.imageWrapper}>
<img src={src} className={_compare_ratios_ ? s.tall : s.wide}/>
</div>
</div>
);
}
}

Answer

I have a resize helper component that I can pass a function to, which looks like this:

class ResizeHelper extends React.Component {

    static propTypes = {
        onWindowResize: PropTypes.func,
    };

    constructor() {
        super();
        this.handleResize = this.handleResize.bind(this);
    }

    componentDidMount() {
        if (this.props.onWindowResize) {
            window.addEventListener('resize', this.handleResize);
        }
    }

    componentWillUnmount() {
        if (this.props.onWindowResize) {
            window.removeEventListener('resize', this.handleResize);
        }
    }

    handleResize(event) {
        if ('function' === typeof this.props.onWindowResize) {
            // we want this to fire immediately the first time but wait to fire again
            // that way when you hit a break it happens fast and only lags if you hit another break immediately
            if (!this.resizeTimer) {
                this.props.onWindowResize(event);
                this.resizeTimer = setTimeout(() => {
                    this.resizeTimer = false;
                }, 250); // this debounce rate could be passed as a prop
            }
        }
    }

    render() {
        return (<div />);
    }
}

Then any component that needs to do something on resize can use it like this:

<ResizeHelper onWindowResize={this.handleResize} />

You also may need to call the passed function once on componentDidMount to set up the UI. Since componentDidMount and componentWillUnmount never get called on the server this works perfectly in my isomorphic App.

Comments