Skip to content

Commit

Permalink
fix(chips): error with undefined or null children (#883)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasecdb authored and Matt Goo committed May 30, 2019
1 parent c0dfb94 commit d733c29
Show file tree
Hide file tree
Showing 6 changed files with 273 additions and 15 deletions.
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"@types/puppeteer": "^1.11.1",
"@types/react": "^16.4.4",
"@types/react-dom": "^16.0.11",
"@types/react-is": "^16.7.1",
"@types/react-router-dom": "^4.3.1",
"@types/uuid": "^3.4.4",
"@types/webpack-env": "^1.13.6",
Expand Down
36 changes: 22 additions & 14 deletions packages/chips/ChipSet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import React from 'react';
import {isElement} from 'react-is';
import classnames from 'classnames';
import {MDCChipSetFoundation} from '@material/chips/chip-set/foundation';
import ChipCheckmark from './ChipCheckmark';
Expand All @@ -35,7 +36,7 @@ export interface ChipSetProps {
choice?: boolean;
filter?: boolean;
input?: boolean;
children: ChipType | ChipType[];
children: ChipType | ChipType[] | React.ReactNode;
}

interface ChipSetState {
Expand Down Expand Up @@ -114,16 +115,17 @@ export default class ChipSet extends React.Component<
}

initChipSelection() {
React.Children.forEach(
this.props.children as ChipType | ChipType[],
(child) => {
const {id} = (child as ChipType).props;
const selected = this.state.selectedChipIds.indexOf(id!) > -1;
if (selected) {
this.state.foundation!.select(id!);
}
React.Children.forEach(this.props.children, (child) => {
if (!child || !isElement(child)) {
return;
}
);

const {id} = child.props as ChipProps;
const selected = this.state.selectedChipIds.indexOf(id!) > -1;
if (selected) {
this.state.foundation!.select(id!);
}
});
this.setState({hasInitialized: true});
}

Expand All @@ -141,17 +143,21 @@ export default class ChipSet extends React.Component<

removeChip = (chipId: string) => {
const {updateChips, children} = this.props;

if (!children) return;
const chips = React.Children.toArray(
children
).slice() as React.ReactElement<ChipProps>[];

const chips = React.Children.toArray(children)
.filter(isElement)
.slice() as React.ReactElement<ChipProps>[];

for (let i = 0; i < chips.length; i++) {
const chip = chips[i];
if (chip.props.id === chipId) {
chips.splice(i, 1);
break;
}
}

const chipsArray = chips.length ? chips.map((chip) => chip.props) : [];
updateChips!(chipsArray);
};
Expand All @@ -169,7 +175,9 @@ export default class ChipSet extends React.Component<
return {height, width};
};

renderChip = (chip: any) => {
renderChip = (chip?: React.ReactNode) => {
if (!chip || !isElement(chip)) return;

const {choice, filter, input} = this.props;
if ((choice || filter || input) && !chip.props.id) {
throw new Error('Chip variant missing required property: id.');
Expand Down
223 changes: 223 additions & 0 deletions packages/chips/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion packages/chips/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@
"@material/chips": "^1.1.1",
"@material/react-ripple": "^0.12.0",
"classnames": "^2.2.6",
"react": "^16.4.2"
"react": "^16.4.2",
"react-is": "^16.8.6"
},
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@types/react": "^16.8.19",
"@types/react-is": "^16.7.1"
}
}
12 changes: 12 additions & 0 deletions test/unit/chips/ChipSet.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -538,3 +538,15 @@ test('#componentWillUnmount destroys foundation', () => {
wrapper.unmount();
td.verify(foundation.destroy());
});

test('should not throw with falsy-value children', () => {
assert.doesNotThrow(() =>
shallow<ChipSet>(
<ChipSet>
{null}
{undefined}
{0}
</ChipSet>
)
);
});

0 comments on commit d733c29

Please sign in to comment.