Skip to content

Commit e05a9ec

Browse files
committed
[fixed] Issue when conditionally rendering Tab/TabPanel
closes #37
1 parent 2742248 commit e05a9ec

File tree

5 files changed

+105
-0
lines changed

5 files changed

+105
-0
lines changed

examples/conditional/app.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
import { Tab, Tabs, TabList, TabPanel } from '../../lib/main';
4+
5+
const App = React.createClass({
6+
getInitialState() {
7+
return {
8+
showA: true,
9+
showB: true,
10+
showC: true
11+
};
12+
},
13+
14+
handleCheckClicked(e) {
15+
const state = {};
16+
state[e.target.name] = e.target.checked;
17+
this.setState(state);
18+
},
19+
20+
render() {
21+
return (
22+
<div style={{padding: 50}}>
23+
<p>
24+
<label>
25+
<input type="checkbox" checked={this.state.showA} name="showA" onChange={this.handleCheckClicked}/>
26+
Show A
27+
</label><br/>
28+
<label>
29+
<input type="checkbox" checked={this.state.showB} name="showB" onChange={this.handleCheckClicked}/>
30+
Show B
31+
</label><br/>
32+
<label>
33+
<input type="checkbox" checked={this.state.showC} name="showC" onChange={this.handleCheckClicked}/>
34+
Show C
35+
</label><br/>
36+
</p>
37+
<Tabs>
38+
<TabList>
39+
{ this.state.showA && <Tab>Tab A</Tab> }
40+
{ this.state.showB && <Tab>Tab B</Tab> }
41+
{ this.state.showC && <Tab>Tab C</Tab> }
42+
</TabList>
43+
{ this.state.showA && <TabPanel>This is tab A</TabPanel> }
44+
{ this.state.showB && <TabPanel>This is tab B</TabPanel> }
45+
{ this.state.showC && <TabPanel>This is tab C</TabPanel> }
46+
</Tabs>
47+
</div>
48+
);
49+
}
50+
});
51+
52+
ReactDOM.render(<App/>, document.getElementById('example'));
53+

examples/conditional/index.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!doctype html>
2+
<meta charset="utf-8"/>
3+
<title>React Tabs</title>
4+
<body>
5+
<div id="example"></div>
6+
<script src="../__build__/shared.js"></script>
7+
<script src="../__build__/conditional.js"></script>
8+

lib/components/Tabs.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,12 @@ module.exports = React.createClass({
214214

215215
// Map children to dynamically setup refs
216216
return React.Children.map(children, (child) => {
217+
// null happens when conditionally rendering TabPanel/Tab
218+
// see https://github.com/rackt/react-tabs/issues/37
219+
if (child === null) {
220+
return null;
221+
}
222+
217223
let result = null;
218224

219225
// Clone TabList and Tab components to have refs
@@ -222,6 +228,12 @@ module.exports = React.createClass({
222228
result = cloneElement(child, {
223229
ref: 'tablist',
224230
children: React.Children.map(child.props.children, (tab) => {
231+
// null happens when conditionally rendering TabPanel/Tab
232+
// see https://github.com/rackt/react-tabs/issues/37
233+
if (tab === null) {
234+
return null;
235+
}
236+
225237
const ref = 'tabs-' + index;
226238
const id = tabIds[index];
227239
const panelId = panelIds[index];

lib/components/__tests__/Tabs-test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,5 +236,25 @@ describe('react-tabs', function() {
236236

237237
ok(!error);
238238
});
239+
240+
it('should gracefully render null', function() {
241+
let error = false;
242+
try {
243+
TestUtils.renderIntoDocument(
244+
<Tabs>
245+
<TabList>
246+
<Tab>Tab A</Tab>
247+
{ false && <Tab>Tab B</Tab> }
248+
</TabList>
249+
<TabPanel>Content A</TabPanel>
250+
{ false && <TabPanel>Content B</TabPanel> }
251+
</Tabs>
252+
);
253+
} catch (e) {
254+
error = true;
255+
}
256+
257+
ok(!error);
258+
});
239259
});
240260
});

lib/helpers/childrenPropType.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,20 @@ module.exports = function childrenPropTypes(props, propName) {
99
const children = props[propName];
1010

1111
React.Children.forEach(children, (child) => {
12+
// null happens when conditionally rendering TabPanel/Tab
13+
// see https://github.com/rackt/react-tabs/issues/37
14+
if (child === null) {
15+
return;
16+
}
17+
1218
if (child.type === TabList) {
1319
React.Children.forEach(child.props.children, (c) => {
20+
// null happens when conditionally rendering TabPanel/Tab
21+
// see https://github.com/rackt/react-tabs/issues/37
22+
if (c === null) {
23+
return;
24+
}
25+
1426
if (c.type === Tab) {
1527
tabsCount++;
1628
} else {

0 commit comments

Comments
 (0)