javascript - 如何在 React 中将 JSX 元素转换为函数组件?
问题描述
我的 React 应用在 App.js 中有以下内容:
const App = () => (
<Router>
<Switch>
... various routes, all working fine ...
<Route exact path={ROUTES.DASHBOARD} render={(props) => <Dashboard {...props} />}/>
</Switch>
</Router>
);
我在仪表板上收到一个错误,上面写着JSX element type 'Dashboard' does not have any construct or call signatures
.
这是因为Dashboard
是这样创建的:
const DashboardPage = ({firebase}:DashboardProps) => {
return (
<div className="mainRoot dashboard">...contents of dashboard...</div>
);
}
const Dashboard = withFirebase(DashboardPage);
export default Dashboard;
并且withFirebase
是:
从'./firebaseContext'导入FirebaseContext;
const withFirebase = (Component:any) => (props:any) => (
<FirebaseContext.Consumer>
{firebase => <Component {...props} firebase={firebase} />}
</FirebaseContext.Consumer>
);
export default withFirebase;
所以 withFirebase 正在导出一个 JSX 元素,这就是 Dashboard。如何确保 withFirebase 正在导出组件?
解决方案
所以 withFirebase 正在导出一个 JSX 元素,这就是 Dashboard。如何确保 withFirebase 正在导出组件?
withFirebase
不是创建 JSX 元素,而是创建一个创建 JSX 元素的函数——换句话说,它是一个函数组件。也许它有助于正确键入它。
const withFirebase = <Props extends {}>(
Component: React.ComponentType<Omit<Props, "firebase"> & { firebase: Firebase | null }>
): React.FC<Props> => (props) => (
<FirebaseContext.Consumer>
{(firebase) => <Component {...props} firebase={firebase} />}
</FirebaseContext.Consumer>
);
这些类型在这个答案中有详细解释。你的上下文值有时null
吗?你能DashboardPage
处理吗,还是我们需要在这里处理?这是确保DashboardPage
只能使用有效Firebase
道具调用的一种方法。
const withFirebase = <Props extends {}>(
Component: React.ComponentType<Omit<Props, "firebase"> & { firebase: Firebase }>
): React.FC<Props> => (props) => (
<FirebaseContext.Consumer>
{(firebase) =>
firebase ? (
<Component {...props} firebase={firebase} />
) : (
<div>Error Loading Firebase App</div>
)
}
</FirebaseContext.Consumer>
);
现在我们已经修复了 HOC,您的Dashboard
组件具有 type React.FC<{}>
。它是一个不带任何道具的功能组件。
你不需要render
为你创建一个内联方法Route
(这实际上会给出关于不兼容道具的错误)。您可以将其设置为component
属性component={Dashboard}
。
完整代码:
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
// placeholder
class Firebase {
app: string;
constructor() {
this.app = "I'm an app";
}
}
const FirebaseContext = React.createContext<Firebase | null>(null);
const withFirebase = <Props extends {}>(
Component: React.ComponentType<Omit<Props, "firebase"> & { firebase: Firebase }>
): React.FC<Props> => (props) => (
<FirebaseContext.Consumer>
{(firebase) =>
firebase ? (
<Component {...props} firebase={firebase} />
) : (
<div>Error Loading Firebase App</div>
)
}
</FirebaseContext.Consumer>
);
interface DashboardProps {
firebase: Firebase;
}
const DashboardPage = ({ firebase }: DashboardProps) => {
console.log(firebase);
return <div className="mainRoot dashboard">...contents of dashboard...</div>;
};
const Dashboard = withFirebase(DashboardPage);
const App = () => {
const firebase = new Firebase();
return (
<FirebaseContext.Provider value={firebase}>
<Router>
<Switch>
<Route component={Dashboard} />
</Switch>
</Router>
</FirebaseContext.Provider>
);
};
export default App;
推荐阅读
- node.js - React + NodeJS - nodemailer 谷歌云功能
- node.js - 使用 Typescript 为可能的 null 值添加一个接口
- visual-studio - 使用 MSBuild、VS 2019、Platform Toolset v142 编译时如何指定“目标平台版本”和“目标平台最低版本”
- laravel - 在 laravel mix 中使用 vue 或 jquery
- python - 如何在python中通过re从字符串中获取数字和字母?
- laravel - 从数据库中为通知中的不同电子邮件动态设置邮件驱动程序
- python - 从另一个模块导入一个模块
- java - 在附加页面上使用倒数计时器
- java - 如何获取 FirebaseListAdapter 中存在的元素数量?
- php - 如何使用嵌套的 do while 循环从数据库中获取菜单和子菜单?