diff --git a/src/components/Tab.jsx b/src/components/Tab.jsx
index 91401a9268..2f23fb2f05 100644
--- a/src/components/Tab.jsx
+++ b/src/components/Tab.jsx
@@ -2,14 +2,6 @@ import React, { useEffect, useRef } from 'react';
import cx from 'clsx';
const DEFAULT_CLASS = 'react-tabs__tab';
-const defaultProps = {
- className: DEFAULT_CLASS,
- disabledClassName: `${DEFAULT_CLASS}--disabled`,
- focus: false,
- id: null,
- selected: false,
- selectedClassName: `${DEFAULT_CLASS}--selected`,
-};
/*
Left for TS migration
@@ -34,24 +26,20 @@ const propTypes = {
tabRef: PropTypes.func, // private
};*/
-const Tab = (props) => {
+const Tab = ({
+ children,
+ className = DEFAULT_CLASS,
+ disabled,
+ disabledClassName = `${DEFAULT_CLASS}--disabled`,
+ focus = false,
+ id = null,
+ selected = false,
+ selectedClassName = `${DEFAULT_CLASS}--selected`,
+ tabIndex,
+ tabRef,
+ ...attributes
+}) => {
let nodeRef = useRef();
- const {
- children,
- className,
- disabled,
- disabledClassName,
- focus,
- id,
- selected,
- selectedClassName,
- tabIndex,
- tabRef,
- ...attributes
- } = {
- ...defaultProps,
- ...props,
- };
useEffect(() => {
if (selected && focus) {
diff --git a/src/components/TabList.jsx b/src/components/TabList.jsx
index c3de9888fb..90b0dacf72 100644
--- a/src/components/TabList.jsx
+++ b/src/components/TabList.jsx
@@ -1,10 +1,6 @@
import React from 'react';
import cx from 'clsx';
-const defaultProps = {
- className: 'react-tabs__tab-list',
-};
-
/*
Left for TS migration
const propTypes = {
@@ -15,12 +11,12 @@ const propTypes = {
PropTypes.object,
]),
};*/
-const TabList = (props) => {
- const { children, className, ...attributes } = {
- ...defaultProps,
- ...props,
- };
+const TabList = ({
+ children,
+ className = 'react-tabs__tab-list',
+ ...attributes
+}) => {
return (
{children}
diff --git a/src/components/TabPanel.jsx b/src/components/TabPanel.jsx
index 30fdcbbc72..c933bb0d67 100644
--- a/src/components/TabPanel.jsx
+++ b/src/components/TabPanel.jsx
@@ -2,11 +2,6 @@ import React from 'react';
import cx from 'clsx';
const DEFAULT_CLASS = 'react-tabs__tab-panel';
-const defaultProps = {
- className: DEFAULT_CLASS,
- forceRender: false,
- selectedClassName: `${DEFAULT_CLASS}--selected`,
-};
/*
Left for TS migration
@@ -23,20 +18,16 @@ const propTypes = {
selectedClassName: PropTypes.string,
};
*/
-const TabPanel = (props) => {
- const {
- children,
- className,
- forceRender,
- id,
- selected,
- selectedClassName,
- ...attributes
- } = {
- ...defaultProps,
- ...props,
- };
+const TabPanel = ({
+ children,
+ className = DEFAULT_CLASS,
+ forceRender = false,
+ selectedClassName = `${DEFAULT_CLASS}--selected`,
+ id,
+ selected,
+ ...attributes
+}) => {
return (
{
@@ -69,23 +41,32 @@ For more information about controlled and uncontrolled mode of react-tabs see ht
* focus: Because we never remove focus from the Tabs this state is only used to indicate that we should focus the current tab.
* It is initialized from the prop defaultFocus, and after the first render it is reset back to false. Later it can become true again when using keys to navigate the tabs.
*/
-const Tabs = (props) => {
- checkPropTypes(propTypes, props, 'prop', 'Tabs');
- const {
- children,
- defaultFocus,
- defaultIndex,
- focusTabOnClick,
- onSelect,
- ...attributes
- } = {
- ...defaultProps,
- ...props,
- };
+const Tabs = ({
+ children,
+ defaultFocus = false,
+ defaultIndex = null,
+ focusTabOnClick = true,
+ forceRenderTabPanel = false,
+ selectedIndex = null,
+ environment = null,
+ disableUpDownKeys = false,
+ disableLeftRightKeys = false,
+ onSelect,
+ ...attributes
+}) => {
+ checkPropTypes(propTypes, { children, onSelect, selectedIndex }, 'prop', 'Tabs');
+
+ // Check for conflicting props
+ if (process.env.NODE_ENV !== 'production' && selectedIndex !== null && defaultIndex !== null) {
+ console.error(
+ 'The prop `selectedIndex` cannot be used together with `defaultIndex` in `Tabs`.\n' +
+ 'Either remove `selectedIndex` to let `Tabs` handle the selected tab internally or remove `defaultIndex` to handle it yourself.'
+ );
+ }
const [focus, setFocus] = useState(defaultFocus);
- const [mode] = useState(getModeFromProps(attributes));
- const [selectedIndex, setSelectedIndex] = useState(
+ const [mode] = useState(getModeFromProps({ selectedIndex }));
+ const [selectedIndexState, setSelectedIndexState] = useState(
mode === MODE_UNCONTROLLED ? defaultIndex || 0 : null,
);
@@ -98,14 +79,14 @@ const Tabs = (props) => {
// Ensure that we handle removed tabs and don't let selectedIndex get out of bounds
const tabsCount = getTabsCount(children);
useEffect(() => {
- if (selectedIndex != null) {
+ if (selectedIndexState != null) {
const maxTabIndex = Math.max(0, tabsCount - 1);
- setSelectedIndex(Math.min(selectedIndex, maxTabIndex));
+ setSelectedIndexState(Math.min(selectedIndexState, maxTabIndex));
}
}, [tabsCount]);
}
- checkForIllegalModeChange(attributes, mode);
+ checkForIllegalModeChange({ selectedIndex }, mode);
const handleSelected = (index, last, event) => {
// Call change event handler
@@ -121,21 +102,35 @@ const Tabs = (props) => {
if (mode === MODE_UNCONTROLLED) {
// Update selected index
- setSelectedIndex(index);
+ setSelectedIndexState(index);
}
};
- let subProps = { ...props, ...attributes };
+ let subProps = {
+ children,
+ defaultFocus,
+ defaultIndex,
+ focusTabOnClick,
+ forceRenderTabPanel,
+ selectedIndex,
+ environment,
+ disableUpDownKeys,
+ disableLeftRightKeys,
+ onSelect,
+ ...attributes
+ };
subProps.focus = focus;
subProps.onSelect = handleSelected;
- if (selectedIndex != null) {
- subProps.selectedIndex = selectedIndex;
+ if (selectedIndexState != null) {
+ subProps.selectedIndex = selectedIndexState;
}
+
delete subProps.defaultFocus;
delete subProps.defaultIndex;
delete subProps.focusTabOnClick;
+
return {children};
};