我正在使用React和Material UI创建一个应用,我想导出一个也具有样式的错误边界HOC。
这是我的代码:
import {
Box,
Button,
Container,
createStyles,
Theme,
Typography,
WithStyles,
} from '@material-ui/core';
import { withStyles } from '@material-ui/styles';
import flowRight from 'lodash/flowRight';
import React, { Component } from 'react';
interface State {
hasError: boolean;
}
const styles = (theme: Theme) =>
createStyles({
root: {
padding: theme.spacing(2, 0),
},
});
type WrapperProps = WithStyles<typeof styles>;
const withErrorBoundary = <P extends {}>(WrappedComponent: React.ComponentType<P>) => {
type Props = P & WrapperProps;
return (properties: Props) =>
class ErrorBoundary extends Component<Props, State> {
public static getDerivedStateFromError(error: any) {
return { hasError: true };
}
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
public componentDidCatch(error: any, errorInfo: any) {
console.error(error, errorInfo);
}
public onBackClick() {
window.location.reload();
}
public render() {
const { classes, ...props } = this.props;
if (this.state.hasError) {
return (
<Container className={classes.root}>
<Box
display='flex'
flexDirection='column'
justifyContent='center'
alignContent='center'
>
<Typography color='primary' variant='h4'>
Ops, ocorreu um erro inexperado. Clique abaixo para voltar.
</Typography>
<Button color='primary' variant='contained' onClick={this.onBackClick}>
Tentar novamente
</Button>
</Box>
</Container>
);
}
return <WrappedComponent {...(props as P)} />;
}
};
};
export default flowRight(
withStyles(styles),
withErrorBoundary
);
我想使用HOC轻松将其添加到路线中:
<Route
exact={true}
path='/:id/home'
component={withErrorBoundary(HomeContainer)}
/>
但是当我执行代码时,出现此错误:
index.js:1375 Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
in Unknown (created by WithStyles(Component))
in WithStyles(Component) (created by Context.Consumer)
in Route (at src/index.tsx:40)
in Switch (at src/index.tsx:36)
in ThemeProvider (at theme-handler.tsx:50)
in ThemeHandler (at src/index.tsx:35)
in Suspense (at src/index.tsx:34)
in Router (created by BrowserRouter)
in BrowserRouter (at src/index.tsx:33)
我在做什么错了?
答案 0 :(得分:0)
高阶组件是一个函数,它接受一个组件并返回一个新组件。
您的HOC是一个返回一个返回组件的函数的函数。
您可以直接在HOC内部返回该类:
const withErrorBoundary = <P extends {}>(
WrappedComponent: React.ComponentType<P>,
) => {
type Props = P & WrapperProps;
return class ErrorBoundary extends Component<Props, State> {
public static getDerivedStateFromError(error: any) {
return { hasError: true };
}
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
public componentDidCatch(error: any, errorInfo: any) {
console.error(error, errorInfo);
}
public onBackClick() {
window.location.reload();
}
public render() {
const { classes, ...props } = this.props;
if (this.state.hasError) {
return (
<Container className={classes.root}>
<Box
display="flex"
flexDirection="column"
justifyContent="center"
alignContent="center"
>
<Typography color="primary" variant="h4">
Ops, ocorreu um erro inexperado. Clique abaixo para voltar.
</Typography>
<Button
color="primary"
variant="contained"
onClick={this.onBackClick}
>
Tentar novamente
</Button>
</Box>
</Container>
);
}
return <WrappedComponent {...(props as P)} />;
}
};
};