react-swipeable-views icon indicating copy to clipboard operation
react-swipeable-views copied to clipboard

Height is not updating properly in Tabs while switching

Open lchandramohan opened this issue 5 years ago • 6 comments

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

lchandramohan avatar Jul 11 '19 10:07 lchandramohan

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

petercutting avatar Jul 17 '19 14:07 petercutting

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 divs 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!

IkechukwuAKalu avatar Jul 23 '19 14:07 IkechukwuAKalu

setting animateHeight={true} did the trick for me but be aware of #177 then

quarkcore avatar Jul 30 '19 13:07 quarkcore

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.

thefrankp avatar Mar 18 '21 03:03 thefrankp

@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!

seungwoncode avatar Nov 08 '23 13:11 seungwoncode

@seungwonleee good to know you've solved it!

IkechukwuAKalu avatar Nov 09 '23 10:11 IkechukwuAKalu