fix: check if component is valid before cloning. fixes #407

This commit is contained in:
Satyajit Sahoo
2018-06-03 16:11:13 +02:00
parent 7aea32afed
commit a6508dcfe2
6 changed files with 55 additions and 40 deletions

View File

@@ -106,8 +106,9 @@ class Card extends React.Component<Props, State> {
const siblings = React.Children.map(
children,
child =>
/* $FlowFixMe */
typeof child === 'object' && child.type ? child.type.displayName : null
React.isValidElement(child) && child.type
? child.type.displayName
: null
);
return (
<AnimatedPaper
@@ -124,9 +125,8 @@ class Card extends React.Component<Props, State> {
{React.Children.map(
children,
(child, index) =>
typeof child === 'object' && child !== null
? /* $FlowFixMe */
React.cloneElement(child, {
React.isValidElement(child)
? React.cloneElement(child, {
index,
total,
siblings,

View File

@@ -36,10 +36,8 @@ class CardActions extends React.Component<Props> {
{React.Children.map(
this.props.children,
child =>
typeof child === 'object' && child !== null
? /* $FlowFixMe */
React.cloneElement(child, {
/* $FlowFixMe */
React.isValidElement(child)
? React.cloneElement(child, {
compact: child.props.compact !== false,
})
: child

View File

@@ -101,24 +101,28 @@ class Dialog extends React.Component<Props, void> {
const backgroundColor = theme.colors.paper;
const childrenArray = React.Children.toArray(children);
/* $FlowFixMe */
const title = childrenArray.find(child => child.type === DialogTitle);
const title = childrenArray.find(
child => React.isValidElement(child) && child.type === DialogTitle
);
const actionBtnsChildren = childrenArray.filter(
/* $FlowFixMe */
child => child && child.type === DialogActions
child => React.isValidElement(child) && child.type === DialogActions
);
const restOfChildren = childrenArray.filter(
child =>
/* $FlowFixMe */
child && child.type !== DialogActions && child.type !== DialogTitle
React.isValidElement(child) &&
child.type !== DialogActions &&
child.type !== DialogTitle
);
let restOfChildrenWithoutTitle = restOfChildren;
if (!title) {
let found = false;
restOfChildrenWithoutTitle = restOfChildren.map(child => {
if (child.type === DialogContent && !found) {
if (
React.isValidElement(child) &&
child.type === DialogContent &&
!found
) {
found = true;
/* $FlowFixMe */
return React.cloneElement(child, {
style: { paddingTop: 24 },
});

View File

@@ -46,9 +46,8 @@ const DialogActions = (props: Props) => (
{React.Children.map(
props.children,
child =>
typeof child === 'object' && child !== null
? /* $FlowFixMe */
React.cloneElement(child, {
React.isValidElement(child)
? React.cloneElement(child, {
compact: true,
})
: child

View File

@@ -154,7 +154,12 @@ class ListAccordion extends React.Component<Props, State> {
</TouchableRipple>
{this.state.expanded
? React.Children.map(children, child => {
if (icon && child && !child.props.icon && !child.props.avatar) {
if (
icon &&
React.isValidElement(child) &&
!child.props.icon &&
!child.props.avatar
) {
return React.cloneElement(child, {
style: [styles.child, child.props.style],
});

View File

@@ -137,9 +137,16 @@ class Toolbar extends React.Component<Props> {
if (Platform.OS === 'ios') {
childrenArray.forEach(child => {
if (!isToolbarContentFound && child.type !== ToolbarContent) {
if (
!isToolbarContentFound &&
React.isValidElement(child) &&
child.type !== ToolbarContent
) {
leftActions++;
} else if (child.type === ToolbarContent) {
} else if (
React.isValidElement(child) &&
child.type === ToolbarContent
) {
isToolbarContentFound = true;
} else {
rightActions++;
@@ -172,25 +179,27 @@ class Toolbar extends React.Component<Props> {
{...rest}
>
<View style={[{ height, marginTop: statusBarHeight }, styles.wrapper]}>
{childrenArray.filter(Boolean).map((child: any, i) => {
const props: { dark: ?boolean, style?: any } = {
dark:
typeof child.props.dark === 'undefined'
? isDark
: child.props.dark,
};
{childrenArray
.filter(child => React.isValidElement(child))
.map((child: any, i) => {
const props: { dark: ?boolean, style?: any } = {
dark:
typeof child.props.dark === 'undefined'
? isDark
: child.props.dark,
};
if (child.type === ToolbarContent) {
// Extra margin between left icon and ToolbarContent
props.style = [
{ marginHorizontal: i === 0 ? 0 : 8 },
centerIos && { alignItems: 'center' },
child.props.style,
];
}
if (child.type === ToolbarContent) {
// Extra margin between left icon and ToolbarContent
props.style = [
{ marginHorizontal: i === 0 ? 0 : 8 },
centerIos && { alignItems: 'center' },
child.props.style,
];
}
return React.cloneElement(child, props);
})}
return React.cloneElement(child, props);
})}
</View>
</Wrapper>
);