我正在尝试在 TypeScript 中实现一个高阶组件,以便我可以将 ErrorBoundary 作为参数传递给高阶组件,然后高阶组件返回用户的当前位置,以便我可以在我的 ErrorBoundary 组件中使用它.
错误边界:
import React from "react";
interface ErrorBoundaryProps {
fallback: React.ReactNode;
children: React.ReactNode;
location: {
pathname: string;
};
}
class ErrorBoundary extends React.Component<ErrorBoundaryProps> {
state = { hasError: false };
static getDerivedStateFromError(error: Error) {
return { hasError: true };
}
componentDidUpdate(previousProps: ErrorBoundaryProps) {
if (previousProps.location.pathname !== this.props.location.pathname) {
this.setState({ hasError: false });
}
}
render() {
if (this.state.hasError) {
return this.props.fallback;
}
return this.props.children;
}
}
export default ErrorBoundary;
WithRouter(高阶组件):
import { useLocation } from "react-router-dom";
function WithRouter(OriginalComponent: React.ComponentType) {
const NewComponent = (props: any) => {
const location = useLocation();
return <OriginalComponent {...props} location={location} />;
};
return NewComponent;
}
显然 TypeScript 编译器不满意,我不知道如何修复它。抱歉,我对此很陌生!
我刚刚尝试过不同的实现,但似乎没有任何效果。
如果这有帮助,这就是 JavaScript 中的工作原理:
import { useLocation } from "react-router-dom";
function WithRouter(OriginalComponent) {
const NewComponent = (props) => {
const location = useLocation();
return <OriginalComponent location={location} {...props} />;
};
return NewComponent;
}
但我只是在努力将其转换为 TypeScript。
我在代码中看到的唯一明显的问题是
React.ComponentType
需要一个参数。
示例:
function withRouter<P extends {}>(Component: React.ComponentType<P>) {
const NewComponent = (props: any) => {
const location = useLocation();
return <Component {...props} location={location} />;
};
return NewComponent;
}
或
const withRouter = <P extends {}>(Component: React.ComponentType<P>) => (
props: any
) => {
const location = useLocation();
return <Component {...props} location={location} />;
};
用途:
const ErrorBoundaryWithRouter = withRouter(ErrorBoundary);
您可能还应该使用从 React-Router-DOM 导出的
Location
类型作为 ErrorBoundaryProps
接口。
import type { Location } from "react-router-dom";
interface ErrorBoundaryProps {
fallback: React.ReactNode;
children: React.ReactNode;
location: Location;
}
或者更准确地说,将
WithRouterProps
定义为单独的接口,并将其扩展为 ErrorBoundaryProps
接口:
import type { Location } from "react-router-dom";
interface WithRouterProps {
location: Location;
}
interface ErrorBoundaryProps extends WithRouterProps {
fallback: React.ReactNode;
children: React.ReactNode;
}
const withRouter = <P extends object>(Component: React.ComponentType<P>) => (
props: Omit<P, keyof WithRouterProps>
) => {
const location = useLocation();
return <Component {...props as P} location={location} />;
};