Skip to content

Commit d647a8e

Browse files
oliviertassinarithe-noob
authored andcommitted
[Tabs] Fix consecutive updates (mui#8831)
1 parent cbbeb81 commit d647a8e

File tree

4 files changed

+41
-10
lines changed

4 files changed

+41
-10
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@
183183
"size-limit": [
184184
{
185185
"path": "build/index.js",
186-
"limit": "93 KB"
186+
"limit": "94 KB"
187187
}
188188
],
189189
"nyc": {

pages/api/tabs.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ filename: /src/Tabs/Tabs.js
66

77
# Tabs
88

9-
Notice that this Component is incompatible with server side rendering.
9+
1010

1111
## Props
1212

src/Tabs/Tabs.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,6 @@ export type TabsMeta = {
144144
right: number,
145145
};
146146

147-
/**
148-
* Notice that this Component is incompatible with server side rendering.
149-
*/
150147
class Tabs extends React.Component<ProvidedProps & Props, State> {
151148
static defaultProps = {
152149
centered: false,
@@ -180,10 +177,13 @@ class Tabs extends React.Component<ProvidedProps & Props, State> {
180177

181178
componentDidUpdate(prevProps, prevState) {
182179
this.updateScrollButtonState();
180+
181+
// The index might have changed at the same time.
182+
// We need to check again the right indicator position.
183+
this.updateIndicatorState(this.props);
184+
183185
if (this.state.indicatorStyle !== prevState.indicatorStyle) {
184186
this.scrollSelectedIntoView();
185-
} else {
186-
this.updateIndicatorState(this.props);
187187
}
188188
}
189189

@@ -335,8 +335,10 @@ class Tabs extends React.Component<ProvidedProps & Props, State> {
335335
};
336336

337337
if (
338-
indicatorStyle.left !== this.state.indicatorStyle.left ||
339-
indicatorStyle.width !== this.state.indicatorStyle.width
338+
(indicatorStyle.left !== this.state.indicatorStyle.left ||
339+
indicatorStyle.width !== this.state.indicatorStyle.width) &&
340+
!Number.isNaN(indicatorStyle.left) &&
341+
!Number.isNaN(indicatorStyle.width)
340342
) {
341343
this.setState({ indicatorStyle });
342344
}

src/Tabs/Tabs.spec.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import React from 'react';
44
import { assert } from 'chai';
55
import { spy, stub, useFakeTimers } from 'sinon';
66
import scroll from 'scroll';
7-
import { createShallow, createMount, getClasses } from '../test-utils';
7+
import { createShallow, createMount, getClasses, unwrap } from '../test-utils';
88
import consoleErrorMock from '../../test/utils/consoleErrorMock';
99
import Tabs from './Tabs';
1010
import TabScrollButton from './TabScrollButton';
1111
import TabIndicator from './TabIndicator';
1212
import Tab from './Tab';
1313

14+
const TabsNaked = unwrap(Tabs);
15+
1416
const noop = () => {};
1517
const fakeTabs = {
1618
getBoundingClientRect: () => ({}),
@@ -207,6 +209,33 @@ describe('<Tabs />', () => {
207209
);
208210
assert.strictEqual(wrapper2.find(TabIndicator).length, 1);
209211
});
212+
213+
it('should update the indicator state no matter what', () => {
214+
const wrapper2 = mount(
215+
<TabsNaked width="md" onChange={noop} value={1} classes={{}} theme={{}}>
216+
<Tab />
217+
<Tab />
218+
</TabsNaked>,
219+
);
220+
const instance = wrapper2.instance();
221+
stub(instance, 'scrollSelectedIntoView');
222+
223+
wrapper2.setState({
224+
indicatorStyle: {
225+
left: 10,
226+
width: 40,
227+
},
228+
});
229+
wrapper2.setProps({
230+
value: 0,
231+
});
232+
233+
assert.strictEqual(
234+
instance.scrollSelectedIntoView.callCount >= 2,
235+
true,
236+
'should have called scrollSelectedIntoView',
237+
);
238+
});
210239
});
211240

212241
it('should warn when the value is invalid', () => {

0 commit comments

Comments
 (0)