8
8
import UncontrolledTabs from './UncontrolledTabs' ;
9
9
import { getTabsCount } from '../helpers/count' ;
10
10
11
+ const MODE_CONTROLLED = 0 ;
12
+ const MODE_UNCONTROLLED = 1 ;
13
+
11
14
export default class Tabs extends Component {
12
15
static defaultProps = {
13
16
defaultFocus : false ,
@@ -40,28 +43,17 @@ export default class Tabs extends Component {
40
43
this . state = Tabs . copyPropsToState ( this . props , { } , props . defaultFocus ) ;
41
44
}
42
45
43
- componentWillReceiveProps ( newProps ) {
44
- if (
45
- process . env . NODE_ENV !== 'production' &&
46
- Tabs . inUncontrolledMode ( newProps ) !== Tabs . inUncontrolledMode ( this . props )
47
- ) {
48
- throw new Error (
49
- `Switching between controlled mode (by using \`selectedIndex\`) and uncontrolled mode is not supported in \`Tabs\`.
50
- For more information about controlled and uncontrolled mode of react-tabs see the README.` ,
51
- ) ;
52
- }
53
- // Use a transactional update to prevent race conditions
54
- // when reading the state in copyPropsToState
55
- // See https://github.com/reactjs/react-tabs/issues/51
56
- this . setState ( state => Tabs . copyPropsToState ( newProps , state ) ) ;
46
+ static getDerivedStateFromProps ( props , state ) {
47
+ return Tabs . copyPropsToState ( props , state ) ;
57
48
}
58
49
59
- static inUncontrolledMode ( props ) {
60
- return props . selectedIndex === null ;
50
+ static getModeFromProps ( props ) {
51
+ return props . selectedIndex === null ? MODE_UNCONTROLLED : MODE_CONTROLLED ;
61
52
}
62
53
63
54
handleSelected = ( index , last , event ) => {
64
55
const { onSelect } = this . props ;
56
+ const { mode } = this . state ;
65
57
66
58
// Call change event handler
67
59
if ( typeof onSelect === 'function' ) {
@@ -74,7 +66,7 @@ For more information about controlled and uncontrolled mode of react-tabs see th
74
66
focus : event . type === 'keydown' ,
75
67
} ;
76
68
77
- if ( Tabs . inUncontrolledMode ( this . props ) ) {
69
+ if ( mode === MODE_UNCONTROLLED ) {
78
70
// Update selected index
79
71
state . selectedIndex = index ;
80
72
}
@@ -85,11 +77,23 @@ For more information about controlled and uncontrolled mode of react-tabs see th
85
77
// preserve the existing selectedIndex from state.
86
78
// If the state has not selectedIndex, default to the defaultIndex or 0
87
79
static copyPropsToState ( props , state , focus = false ) {
80
+ if (
81
+ process . env . NODE_ENV !== 'production' &&
82
+ state . mode !== undefined &&
83
+ state . mode !== Tabs . getModeFromProps ( props )
84
+ ) {
85
+ throw new Error (
86
+ `Switching between controlled mode (by using \`selectedIndex\`) and uncontrolled mode is not supported in \`Tabs\`.
87
+ For more information about controlled and uncontrolled mode of react-tabs see the README.` ,
88
+ ) ;
89
+ }
90
+
88
91
const newState = {
89
92
focus,
93
+ mode : Tabs . getModeFromProps ( props ) ,
90
94
} ;
91
95
92
- if ( Tabs . inUncontrolledMode ( props ) ) {
96
+ if ( newState . mode === MODE_UNCONTROLLED ) {
93
97
const maxTabIndex = getTabsCount ( props . children ) - 1 ;
94
98
let selectedIndex = null ;
95
99
0 commit comments