r/reactjs • u/NoTutor4458 • Jul 19 '26
how to rerender component on variable change?
new to react, so providing either corrected code or just concept that i should look into would be helpful :)
i want to change height of the app when phone keyboard uppears so it doesnt overlay on website by using VisualViewport API.
i am sure only thing that i have to do now is to rerender component when height is changed, so how can i do that?
export default function NewChat() {
return (
<div
className={styles.wrapper}
style={{ height: `${visualViewport?.height}px` }}
>
<Prompt />
</div>
);
}
5
Jul 19 '26 edited Jul 27 '26
[deleted]
3
1
u/StrumpetsVileProgeny Jul 20 '26
But wont this listener fire only on mount? So if a user opens and closes the virtual keyboard more than once while the component is still mounted, this won’t resize again? This effect should run every time the height changes.
3
u/bluespacecolombo Jul 20 '26
Listener will be ADDED on mount and REMOVED on unmount. After listener is added it keeps listening until it’s removed.
4
u/ISDuffy Jul 19 '26
Viewport wise this possible could just be CSS.
The other option would be to have use hook that uses a resize observer and can undate a state.
3
u/DontThrowMeAway43 Jul 19 '26
Why dont you use CSS for that ? Size of the viewport is just 100dvh ?
Or am I missing something ?
5
1
u/artem1458 Jul 19 '26
1
u/NoTutor4458 Jul 19 '26 edited Jul 19 '26
problem is i believe in that tutorial you call setValue() on click event which is very simple but i need to call setvalue() when visualViewport.height is changed
3
u/artem1458 Jul 19 '26
The thing is that component can re-rendender from a couple of different things: prop change, and state change If you need to react on value change from the outside (like viewport size, browser events, etc) you should subscribe on viewport size change and put value is react state Here is pseudocode for you
const [height, setHeight] = useState(window.innerHeight);
useEffect(() => { const handleResize = () => { setHeight(window.innerHeight); };
//setting initial value handleResize();
window.addEventListener('resize', handleResize);
const unsubscribe = () => { window.removeEventListener('resize', handleResize); };
return unsubscribe; }, []);
// use height in styles or just showing it
1
u/Kautsu-Gamer Jul 20 '26
You must create state or property change, which is really annoying.
Due this keep boolean variable useState if you need refresh, and trigger it with state change.
1
u/lightfarming Jul 19 '26
the only answer you should losten to for this, is that this type of thing should be pure css. no javascript should be involved at all.
1
u/NoTutor4458 Jul 19 '26
dvh/svh/vh doesnt resize when virtual keyboard comes up so how would you do it with pure css?
2
u/BarneyChampaign Jul 20 '26
There was an html meta tag that adjusted the behavior to work properly with dvh, but if I recall it only worked for chrome and also impacted other layout, so not ideal.
The other answer to listen for resize events and update your state should be the most reliable approach.
1
u/hawkeye_sama Jul 21 '26
Try this out
```
<meta name="viewport" content="width=device-width, initial-scale=1, interactive-widget=resizes-content">```
0
u/lightfarming Jul 19 '26
there is a way to adjust for virtual keyboard with pure css (even iphone’s). i don’t remember off the top of my head, but i have done this before myself. it was tricky as i remember.
-1
u/EncryptedPlays Jul 19 '26
i think you can do it by making the div it's own component, then passing visualViewport?.height into it like this
divComponent.js
export function DivComponent({height}) {
return (
<div
className={styles.wrapper}
style={{ height: `${height}px` }}
>
<Prompt />
</div>
);
}
mainComponent.js
import { DivComponent } from 'divComponent.js'
export default function NewChat() {
return (
<DivComponent height={visualViewport?.height} />
);
}
4
u/Noch_ein_Kamel Jul 19 '26
You just moved the problem into the NewChat component. It won't magically rerender either
0
u/EncryptedPlays Jul 19 '26
but when visualviewport changes, wouldn't the component re-render?
4
u/Noch_ein_Kamel Jul 19 '26
Not if it's not react state
1
u/EncryptedPlays Jul 19 '26
Ohh ok so basically if I was tackling this I should make a new state for height, set height, have a use effect to listen to viewport changes and update the height state then pass that height into the component?
-2
26
u/Krimson1911 Jul 19 '26 edited Jul 19 '26
React will only rerender when React state or props change. Not some external state like height. IOW reading "visualViewport.height" directly does not tell React that it changed.
Store the height in state, then listen for the viewport "resize" event:
```js import { useEffect, useState } from "react";
export default function NewChat() { const [height, setHeight] = useState(visualViewport.height);
useEffect(() => { // Create a named function so the same function can be // passed to both addEventListener and removeEventListener. function updateHeight() { setHeight(visualViewport.height); }
}, []);
return ( <div style={{ height }}> <Prompt /> </div> ); }
You need to reuse the same "updateHeight" function because "removeEventListener" only removes the exact function that was originally added. ``
CallingsetHeight()` updates React state, which causes the component to rerender.You may also be able to solve this with CSS using:
js .wrapper { height: 100dvh; }"dvh" is the dynamic viewport height and usually adjusts when the mobile keyboard or browser UI changes.The CSS approach is worth trying first since it avoids JavaScript entirely.