react-swipeable-views
react-swipeable-views copied to clipboard
Height is not updating properly in Tabs while switching
I am using Material UI Tab react-swipeable-views in my ReactJs Application. I have 2 tabs. First Tab 1 content is approximately 100px. Tab 2 content is 1000px. While loading Application I load Tab 1. Its having proper content height. When I click Tab 2 and Tab 1 again. Tab 1 Height is updated 1000+px. Every time I navigate back and forth.. Height is increasing. Both Tabs having 1000+px height. Please help me to resolve this issue.
I have tried few solutions provided but it didn't work. Sol 1 : I used this.swipeableActions.updateHeight(); method in componentDidUpdate and componentWillMount. added AnimateHeight={true}.
Sol 2 : Added the display;none style to non selected Tab.
Expected Behavior
While Changing the Tabs, Tab Height should be maintained as Tab 1 100px, Tab 2 1000px. (both value are dynamic)
Current Behavior
Currently Once I change from Tab 1 to Tab 2. Tab 1 also having Tab 2 height. Keep on clicking the tabs is increasing the Height Value.
Steps to Reproduce (for bugs)
https://codesandbox.io/s/material-demo-rygr1
Your Environment
Tech | Version |
---|---|
react-swipeable-views | ^0.13.1 |
React | 16.8.6 |
platform | Windows |
I think I see the same problem as you . All the tabs effectively have the height of the longest tab.
So a short tab with say only 1 line might scroll way off screen if there is another tab that is pages deep
I would like all tabs to have their own intinsic length so that they do not scroll more then necessary
Also I would like to be able to scrollTo somewhere as each tab comes into view but I cannot get the onSwitching handler to fire
I had the same issue but found a workaround. What I did was to calculate the height of the container element, then use it to set the height of the SwipeableViews
component.
Assuming I have multiple div
s with a class (className)
of my-aa-tabs
, I get the current index
of the active tab, use the index
to get the clientHeight
of the active div
, then update the SwipeableViews
component.
Example:
<SwipeableViews
axis={direction === "rtl" ? "x-reverse" : "x"}
index={active}
onChangeIndex={(index) => {
this.setState({ active: index }, () => {
setTimeout(() => {
const height = document.getElementsByClassName("my-aa-tabs")[index].clientHeight;
this.setState({ height });
}, 10); // I use this handle cases where the height is calculated before the view updates
});
}}
containerStyle={{ WebkitOverflowScrolling: "touch", height }}
>
<div className={classes.tabContent} key={key}>
<div className="my-aa-tabs">
Hello IK
</div>
<div className="my-aa-tabs">
Hello LEO
</div>
</div>
</SwipeableViews>
I didn't actually run the above code but it shows the idea. Hope it helps.
Cheers!
setting animateHeight={true}
did the trick for me but be aware of #177 then
Here's a little more comment around this issue.
The animateHeight prop has been brilliant for the past couple years, Then upgrades to Safari and Chrome browsers seem to have broken this feature. All slides have the longest slides length. Firefox still works fine.
Our application has long complicated screens that work best once all loaded and react-swipeable-views keeps the UI experience nice and fast.
Now this is a horrible hack of a solution that you can feel free to hate on but it got us out of jail. Set the slides that are not on the screen to a display: 'none'. Okay the slides don't look as nice coming in and out but so worth it to not have a scroll bar and white space issue. Particularly if you have other split screen components and scrolls going on.
So implement the animateHeight as in the demos with this.context.swipeableViews.slideUpdateHeight() in the slides etc and then you end up with something like at the top level.
<SwipeableViews
action={actions => {
this.swipeableActions = actions
}}
animateHeight
index={index}>
<div style={{ display: (index === 1) ? 'block' : 'none' }}>
<Slide1/>
</div>
<div style={{ display: (index === 2) ? 'block' : 'none' }}>
<Slide2/>
</div>
<div style={{ display: (index === 3) ? 'block' : 'none' }}>
<Slide3/>
</div>
</SwipeableViews>
Don't hate too hard, everyone hacks behind closed doors.
@IkechukwuAKalu I solved it in a slightly different way, but thanks to it, I was able to get an idea and solve it. Thank you!
@seungwonleee good to know you've solved it!