Skip to content

Commit fa498b5

Browse files
[core] Document the non supported children properties
1 parent d6faa2d commit fa498b5

17 files changed

+97
-56
lines changed

packages/material-ui/src/BottomNavigationAction/BottomNavigationAction.js

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import PropTypes from 'prop-types';
55
import classNames from 'classnames';
66
import withStyles from '../styles/withStyles';
77
import ButtonBase from '../ButtonBase';
8+
import unsupportedProp from '../utils/unsupportedProp';
89

910
export const styles = theme => ({
1011
root: {
@@ -105,6 +106,11 @@ class BottomNavigationAction extends React.Component {
105106
}
106107

107108
BottomNavigationAction.propTypes = {
109+
/**
110+
* This property isn't supported.
111+
* Use the `component` property if you need to change the children structure.
112+
*/
113+
children: unsupportedProp,
108114
/**
109115
* Override or extend the styles applied to the component.
110116
* See [CSS API](#css-api) below for more details.

packages/material-ui/src/Chip/Chip.js

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import keycode from 'keycode';
55
import CancelIcon from '../internal/svg-icons/Cancel';
66
import withStyles from '../styles/withStyles';
77
import { emphasize, fade } from '../styles/colorManipulator';
8+
import unsupportedProp from '../utils/unsupportedProp';
89
import '../Avatar/Avatar'; // So we don't have any override priority issue.
910

1011
export const styles = theme => {
@@ -202,6 +203,11 @@ Chip.propTypes = {
202203
* Avatar element.
203204
*/
204205
avatar: PropTypes.element,
206+
/**
207+
* This property isn't supported.
208+
* Use the `component` property if you need to change the children structure.
209+
*/
210+
children: unsupportedProp,
205211
/**
206212
* Override or extend the styles applied to the component.
207213
* See [CSS API](#css-api) below for more details.

packages/material-ui/src/Chip/Chip.test.js

+7-29
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,7 @@ describe('<Chip />', () => {
2727
let wrapper;
2828

2929
before(() => {
30-
wrapper = shallow(
31-
<Chip className="my-Chip" data-my-prop="woofChip">
32-
Text Chip
33-
</Chip>,
34-
);
30+
wrapper = shallow(<Chip className="my-Chip" data-my-prop="woofChip" />);
3531
});
3632

3733
it('should render a div containing a span', () => {
@@ -56,11 +52,7 @@ describe('<Chip />', () => {
5652

5753
before(() => {
5854
handleClick = () => {};
59-
wrapper = shallow(
60-
<Chip className="my-Chip" data-my-prop="woofChip" onClick={handleClick}>
61-
Text Chip
62-
</Chip>,
63-
);
55+
wrapper = shallow(<Chip className="my-Chip" data-my-prop="woofChip" onClick={handleClick} />);
6456
});
6557

6658
it('should render a div containing a span', () => {
@@ -82,9 +74,7 @@ describe('<Chip />', () => {
8274
it('should apply user value of tabIndex', () => {
8375
wrapper = shallow(
8476
// eslint-disable-next-line jsx-a11y/tabindex-no-positive
85-
<Chip onClick={() => {}} tabIndex={5}>
86-
{'Text Chip'}
87-
</Chip>,
77+
<Chip onClick={() => {}} tabIndex={5} />,
8878
);
8979
assert.strictEqual(wrapper.props().tabIndex, 5);
9080
});
@@ -180,11 +170,7 @@ describe('<Chip />', () => {
180170
it('should call onKeyDown when a key is pressed', () => {
181171
const anyKeydownEvent = { keycode: keycode('p') };
182172
const onKeyDownSpy = spy();
183-
wrapper = mount(
184-
<Chip classes={{}} onKeyDown={onKeyDownSpy}>
185-
Text Chip
186-
</Chip>,
187-
);
173+
wrapper = mount(<Chip classes={{}} onKeyDown={onKeyDownSpy} />);
188174
wrapper.find('div').simulate('keydown', anyKeydownEvent);
189175
assert.strictEqual(onKeyDownSpy.callCount, 1, 'should have called onKeyDown');
190176
assert.strictEqual(
@@ -197,7 +183,7 @@ describe('<Chip />', () => {
197183

198184
describe('escape', () => {
199185
it('should unfocus when a esc key is pressed', () => {
200-
const wrapper2 = mount(<ChipNaked classes={{}}>Text Chip</ChipNaked>);
186+
const wrapper2 = mount(<ChipNaked classes={{}} />);
201187
const handleBlur = spy();
202188
wrapper2.instance().chipRef.blur = handleBlur;
203189
wrapper2.find('div').simulate('keydown', {
@@ -212,11 +198,7 @@ describe('<Chip />', () => {
212198
let onClickSpy;
213199
before(() => {
214200
onClickSpy = spy();
215-
wrapper = mount(
216-
<ChipNaked classes={{}} onClick={onClickSpy}>
217-
Text Chip
218-
</ChipNaked>,
219-
);
201+
wrapper = mount(<ChipNaked classes={{}} onClick={onClickSpy} />);
220202
});
221203

222204
afterEach(() => {
@@ -251,11 +233,7 @@ describe('<Chip />', () => {
251233
describe('onDelete is defined and `backspace` is pressed', () => {
252234
it('should call onDelete', () => {
253235
const onDeleteSpy = spy();
254-
const wrapper2 = mount(
255-
<ChipNaked classes={{}} onDelete={onDeleteSpy}>
256-
Text Chip
257-
</ChipNaked>,
258-
);
236+
const wrapper2 = mount(<ChipNaked classes={{}} onDelete={onDeleteSpy} />);
259237

260238
const preventDefaultSpy = spy();
261239
const backspaceKeydownEvent = {

packages/material-ui/src/CssBaseline/CssBaseline.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ CssBaseline.propTypes = {
4646
classes: PropTypes.object.isRequired,
4747
};
4848

49-
CssBaseline.propTypes = exactProp(CssBaseline.propTypes, 'CssBaseline');
49+
CssBaseline.propTypes = exactProp(CssBaseline.propTypes);
5050

5151
CssBaseline.defaultProps = {
5252
children: null,

packages/material-ui/src/Hidden/HiddenJs.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,6 @@ HiddenJs.propTypes = {
130130
xsUp: PropTypes.bool,
131131
};
132132

133-
HiddenJs.propTypes = exactProp(HiddenJs.propTypes, 'HiddenJs');
133+
HiddenJs.propTypes = exactProp(HiddenJs.propTypes);
134134

135135
export default withWidth()(HiddenJs);

packages/material-ui/src/Portal/Portal.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,6 @@ Portal.propTypes = {
7272
onRendered: PropTypes.func,
7373
};
7474

75-
Portal.propTypes = exactProp(Portal.propTypes, 'Portal');
75+
Portal.propTypes = exactProp(Portal.propTypes);
7676

7777
export default Portal;

packages/material-ui/src/RootRef/RootRef.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,6 @@ RootRef.propTypes = {
7070
rootRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]).isRequired,
7171
};
7272

73-
RootRef.propTypes = exactProp(RootRef.propTypes, 'RootRef');
73+
RootRef.propTypes = exactProp(RootRef.propTypes);
7474

7575
export default RootRef;

packages/material-ui/src/Tab/Tab.js

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import classNames from 'classnames';
66
import withStyles from '../styles/withStyles';
77
import ButtonBase from '../ButtonBase';
88
import { capitalize } from '../utils/helpers';
9+
import unsupportedProp from '../utils/unsupportedProp';
910

1011
export const styles = theme => ({
1112
root: {
@@ -200,6 +201,11 @@ class Tab extends React.Component {
200201
}
201202

202203
Tab.propTypes = {
204+
/**
205+
* This property isn't supported.
206+
* Use the `component` property if you need to change the children structure.
207+
*/
208+
children: unsupportedProp,
203209
/**
204210
* Override or extend the styles applied to the component.
205211
* See [CSS API](#css-api) below for more details.

packages/material-ui/src/styles/MuiThemeProvider.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ MuiThemeProvider.propTypes = {
131131
theme: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired,
132132
};
133133

134-
MuiThemeProvider.propTypes = exactProp(MuiThemeProvider.propTypes, 'MuiThemeProvider');
134+
MuiThemeProvider.propTypes = exactProp(MuiThemeProvider.propTypes);
135135

136136
MuiThemeProvider.childContextTypes = {
137137
...themeListener.contextTypes,

packages/material-ui/src/utils/exactProp.js

+10-7
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,25 @@
33
// However, in order to reduce the number of dependencies and to remove some extra safe checks
44
// the module was forked.
55

6+
// Only exported for test purposes.
67
export const specialProperty = 'exact-prop: \u200b';
78

8-
export default function exactProp(propTypes: Object, componentNameInError: string) {
9+
function exactProp(propTypes: Object) {
910
return {
1011
...propTypes,
1112
// eslint-disable-next-line prefer-arrow-callback
1213
[specialProperty]: props => {
13-
const unknownProps = Object.keys(props).filter(prop => !propTypes.hasOwnProperty(prop));
14-
if (unknownProps.length > 0) {
15-
return new TypeError(
16-
`${componentNameInError}: unknown props found: ${unknownProps.join(
17-
', ',
18-
)}. Please remove the unknown properties.`,
14+
const unsupportedProps = Object.keys(props).filter(prop => !propTypes.hasOwnProperty(prop));
15+
if (unsupportedProps.length > 0) {
16+
return new Error(
17+
`The following properties are not supported: ${unsupportedProps
18+
.map(prop => `\`${prop}\``)
19+
.join(', ')}. Please remove them.`,
1920
);
2021
}
2122
return null;
2223
},
2324
};
2425
}
26+
27+
export default exactProp;

packages/material-ui/src/utils/exactProp.test.js

+10-13
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,12 @@ import { assert } from 'chai';
44
import exactProp, { specialProperty } from './exactProp';
55

66
describe('exactProp()', () => {
7-
const componentNameInError = 'componentNameInError';
87
let exactPropTypes;
98

109
before(() => {
11-
exactPropTypes = exactProp(
12-
{
13-
bar: {},
14-
},
15-
componentNameInError,
16-
);
10+
exactPropTypes = exactProp({
11+
bar: {},
12+
});
1713
});
1814

1915
it('should have the right shape', () => {
@@ -22,22 +18,23 @@ describe('exactProp()', () => {
2218
});
2319

2420
describe('exactPropTypes', () => {
25-
let props;
26-
2721
it('should return null for supported properties', () => {
28-
props = {
22+
const props = {
2923
bar: false,
3024
};
3125
const result = exactPropTypes[specialProperty](props);
3226
assert.strictEqual(result, null);
3327
});
3428

35-
it('should return an error for unknown properties', () => {
36-
props = {
29+
it('should return an error for unsupported properties', () => {
30+
const props = {
3731
foo: true,
3832
};
3933
const result = exactPropTypes[specialProperty](props);
40-
assert.match(result.message, /componentNameInError: unknown props found: foo/);
34+
assert.match(
35+
result.message,
36+
/The following properties are not supported: `foo`. Please remove them/,
37+
);
4138
});
4239
});
4340
});

packages/material-ui/src/utils/requirePropFactory.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @flow weak
22

3-
const requirePropFactory = (componentNameInError: string) => {
3+
function requirePropFactory(componentNameInError: string) {
44
const requireProp = (requiredProp: string) => (
55
props: Object,
66
propName: string,
@@ -20,6 +20,6 @@ const requirePropFactory = (componentNameInError: string) => {
2020
return null;
2121
};
2222
return requireProp;
23-
};
23+
}
2424

2525
export default requirePropFactory;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// @flow
2+
3+
function unsupportedProp(
4+
props: Object,
5+
propName: string,
6+
componentName?: string,
7+
location?: string,
8+
propFullName?: string,
9+
) {
10+
const propFullNameSafe = propFullName || propName;
11+
12+
if (typeof props[propName] !== 'undefined') {
13+
return new Error(`The property \`${propFullNameSafe}\` is not supported. Please remove it.`);
14+
}
15+
16+
return null;
17+
}
18+
19+
export default unsupportedProp;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { assert } from 'chai';
2+
import unsupportedProp from './unsupportedProp';
3+
4+
describe('unsupportedProp', () => {
5+
const propName = 'children';
6+
const componentName = 'ComponentName';
7+
const location = 'prop';
8+
const propFullName = null;
9+
10+
it('should return null for supported properties', () => {
11+
const props = {};
12+
const result = unsupportedProp(props, propName, componentName, location, propFullName);
13+
assert.strictEqual(result, null);
14+
});
15+
16+
it('should return an error for unsupported properties', () => {
17+
const props = {
18+
children: null,
19+
};
20+
const result = unsupportedProp(props, propName, componentName, location, propFullName);
21+
assert.match(result.message, /The property `children` is not supported. Please remove it/);
22+
});
23+
});

pages/api/bottom-navigation-action.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ filename: /packages/material-ui/src/BottomNavigationAction/BottomNavigationActio
1212

1313
| Name | Type | Default | Description |
1414
|:-----|:-----|:--------|:------------|
15+
| <span class="prop-name">children</span> | <span class="prop-type">unsupportedProp |   | This property isn't supported. Use the `component` property if you need to change the children structure. |
1516
| <span class="prop-name">classes</span> | <span class="prop-type">object |   | Override or extend the styles applied to the component. See [CSS API](#css-api) below for more details. |
1617
| <span class="prop-name">icon</span> | <span class="prop-type">node |   | The icon element. |
1718
| <span class="prop-name">label</span> | <span class="prop-type">node |   | The label element. |

pages/api/chip.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Chips represent complex entities in small blocks, such as a contact.
1313
| Name | Type | Default | Description |
1414
|:-----|:-----|:--------|:------------|
1515
| <span class="prop-name">avatar</span> | <span class="prop-type">element |   | Avatar element. |
16+
| <span class="prop-name">children</span> | <span class="prop-type">unsupportedProp |   | This property isn't supported. Use the `component` property if you need to change the children structure. |
1617
| <span class="prop-name">classes</span> | <span class="prop-type">object |   | Override or extend the styles applied to the component. See [CSS API](#css-api) below for more details. |
1718
| <span class="prop-name">clickable</span> | <span class="prop-type">bool | <span class="prop-default">false</span> | If true, the chip will appear clickable, and will raise when pressed, even if the onClick property is not defined. This can be used, for example, along with the component property to indicate an anchor Chip is clickable. |
1819
| <span class="prop-name">component</span> | <span class="prop-type">union:&nbsp;string&nbsp;&#124;<br>&nbsp;func&nbsp;&#124;<br>&nbsp;object<br> | <span class="prop-default">'div'</span> | The component used for the root node. Either a string to use a DOM element or a component. |

pages/api/tab.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ filename: /packages/material-ui/src/Tab/Tab.js
1212

1313
| Name | Type | Default | Description |
1414
|:-----|:-----|:--------|:------------|
15+
| <span class="prop-name">children</span> | <span class="prop-type">unsupportedProp |   | This property isn't supported. Use the `component` property if you need to change the children structure. |
1516
| <span class="prop-name">classes</span> | <span class="prop-type">object |   | Override or extend the styles applied to the component. See [CSS API](#css-api) below for more details. |
1617
| <span class="prop-name">disabled</span> | <span class="prop-type">bool | <span class="prop-default">false</span> | If `true`, the tab will be disabled. |
1718
| <span class="prop-name">icon</span> | <span class="prop-type">node |   | The icon element. |

0 commit comments

Comments
 (0)