I am trying to change the height of a container, when in mobile landscape mode only. I am playing around in the developer tools to swap the orientation of a mobile device but it only works on the first render. I am new to react hooks so not sure if I am implementing it right.
The idea is that I am testing that once in landscape, if it's on mobile the height should be less than 450px (which is the check I am doing for the if statement)
Could someone point me in the right direction, please?
Thanks!
const bikeImageHeight = () => {
const windowViewportHeight = window.innerHeight;
const isLandscape = window.orientation === 90 || window.orientation === -90;
let bikeImgHeight = 0;
if (windowViewportHeight <= 450 && isLandscape) {
bikeImgHeight = windowViewportHeight - 50;
}
return bikeImgHeight;
};
useEffect(() => {
bikeImageHeight();
window.addEventListener("resize", bikeImageHeight);
return () => {
window.removeEventListener("resize", bikeImageHeight);
};
}, []);
I am trying to change the height of a container, when in mobile landscape mode only. I am playing around in the developer tools to swap the orientation of a mobile device but it only works on the first render. I am new to react hooks so not sure if I am implementing it right.
The idea is that I am testing that once in landscape, if it's on mobile the height should be less than 450px (which is the check I am doing for the if statement)
Could someone point me in the right direction, please?
Thanks!
const bikeImageHeight = () => {
const windowViewportHeight = window.innerHeight;
const isLandscape = window.orientation === 90 || window.orientation === -90;
let bikeImgHeight = 0;
if (windowViewportHeight <= 450 && isLandscape) {
bikeImgHeight = windowViewportHeight - 50;
}
return bikeImgHeight;
};
useEffect(() => {
bikeImageHeight();
window.addEventListener("resize", bikeImageHeight);
return () => {
window.removeEventListener("resize", bikeImageHeight);
};
}, []);
Share
Improve this question
asked Oct 15, 2019 at 15:26
markmark
2453 silver badges14 bronze badges
0
3 Answers
Reset to default 7The useEffect
hook is not expected to fire on orientation change. It defines a callback that will fire when the ponent re-renders. The question then is how to trigger a re-render when the screen orientation changes. A re-render occurs when there are changes to a ponents props or state.
Lets make use of another related stackoverflow answer to build a useWindowDimensions
hook. This allows us to hook into the windows size as ponent state so any changes will cause a re-render.
useWindowDimensions.js
import { useState, useEffect } from 'react';
function getWindowDimensions() {
const { innerWidth: width, innerHeight: height } = window;
return {
width,
height
};
}
export default function useWindowDimensions() {
const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
useEffect(() => {
function handleResize() {
setWindowDimensions(getWindowDimensions());
}
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return windowDimensions;
}
You can then use that hook in your ponent. Something like:
BikeImage.js
import React from 'react'
import useWindowDimensions from './useWindowDimensions'
export default () => {
const windowDimensions = useWindowDimensions();
// Define these helper functions as you like
const width = getImageWidth(windowDimensions.width)
const height = getImageHeight(windowDimensions.height)
// AppImage is a ponent defined elsewhere which takes
// at least width, height and src props
return <AppImage width={width} height={height} src="..." .../>
}
Here is a custom hook that fires on orientation change,
import React, {useState, useEffect} from 'react';
// Example usage
export default () => {
const orientation = useScreenOrientation();
return <p>{orientation}</p>;
}
function useScreenOrientation() {
const [orientation, setOrientation] = useState(window.screen.orientation.type);
useEffect(() => {
const handleOrientationChange= () => setOrientation(window.screen.orientation.type);
window.addEventListener('orientationchange', handleOrientationChange);
return () => window.removeEventListener('orientationchange', handleOrientationChange);
}, []);
return orientation;
}
Hope this takes you to the right direction.
You need to trigger a re-render, which can be done by setting state inside of your bikeImageHeight
.
const [viewSize, setViewSize] = useState(0)
const bikeImageHeight = () => {
const windowViewportHeight = window.innerHeight;
const isLandscape = window.orientation === 90 || window.orientation === -90;
let bikeImgHeight = 0;
if (windowViewportHeight <= 450 && isLandscape) {
bikeImgHeight = windowViewportHeight - 50;
}
setViewSize(bikeImgHeight)
return bikeImgHeight;
};
And per the ments conversation, here's how you'd use debounce:
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
const YourComponent = () => {
const bikeImageHeight = () => {
const windowViewportHeight = window.innerHeight;
const isLandscape = window.orientation === 90 || window.orientation === -90;
let bikeImgHeight = 0;
if (windowViewportHeight <= 450 && isLandscape) {
bikeImgHeight = windowViewportHeight - 50;
}
setViewSize(bikeImgHeight)
return bikeImgHeight;
};
const debouncedBikeHeight = debounce(bikeImageHeight, 200)
useEffect(() => {
bikeImageHeight();
window.addEventListener("resize", debouncedBikeHeight);
return () => {
window.removeEventListener("resize", debouncedBikeHeight);
};
}, []);
return <div>some jsx</div>
}
Example debounce taken from here: https://davidwalsh.name/javascript-debounce-function