#reactjs #typescript
Вопрос:
Вместо жесткого кодирования моих маршрутов в компоненте приложения я определил файл Routes.ts:
import Login from "../components/Login/Login";
import Dashboard from "../components/Dashboard/Dashboard";
import PageNotFound from "../components/PageNotFound/PageNotFound";
import {ReactElement, ReactNode} from "react";
const routes: Array<{
path: string,
component: ReactElement,
is_private: boolean
}> = [
{
path: '/',
component: Login,
is_private: false
},
{
path: '/dashboard',
component: Dashboard,
is_private: true
},
{
path: '/*',
component: PageNotFound,
is_private: false
}
];
export default routes;
Который я затем использую следующим образом:
const App: React.FC = () => {
return (
<div className="wrapper">
<h1>My App</h1>
<BrowserRouter>
<Routes>
{routes.map((route) => (
<Route path={route.path}
key={route.path}
element={route.component} />
))}
</Routes>
</BrowserRouter>
</div>
);
}
Однако, поскольку мои компоненты имеют тип React.FC
, я не могу заставить их удовлетворять типу ReactElement:
TS2739: Type 'FunctionComponent<{}>' is missing the following properties from type 'ReactElement<any, string | JSXElementConstructor<any>>': type, props, key
Я пробовал:
- Изменение компонентов на JSX.Element
- компонент: ReactNode
- компонент: FC
Но ни один из них не работает как типы моего компонента (FC) и тип, ожидаемый маршрутом.элемент (ReactElement) не может быть согласован.
Я даже пытался изменить component на any
type, который компилируется, но приводит к ошибке во время выполнения:
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.
Кто-нибудь был бы так любезен, чтобы подтолкнуть меня в правильном направлении?
Комментарии:
1. пожалуйста, предоставьте воспроизводимый пример
2. вы пытались предоставить
component={route.component}
вместоelement=
3. harrymt.com/blog/2020/05/20/react-typescript-react-fc.html просто оставлю это здесь, может быть, будет полезно узнать
4. компонент @SinanYaman больше не существует в используемой мной версии react-router-dom, AFAIK он был переименован в element .
Ответ №1:
Чтобы ваш routes
массив допускал любой тип компонента (FC или любой другой), вы можете установить тип равным be React.JSXElementConstructor
. Это избавляет от необходимости определять все компоненты как FC
. Этот тип принимает аргумент реквизита, но если вы не заботитесь о реквизите, вы можете просто установить его в any
:
const routes: Array<{
path: string,
component: React.JSXElementConstructor<any>,
is_private: boolean
}> = [
Комментарии:
1. Спасибо, это было именно то, что я искал!
Ответ №2:
Почему вы вводите свои компоненты в массив маршрутов как ReactElement
? Вы пробовали использовать FC
вместо этого?
Утверждение, что это массив ReactElements, приведет к конфликту с ожидаемыми типами ReactRouters. Тем не менее, я предполагаю, что компоненты вашей страницы на самом деле являются React.Тип ФК?
import Login from "../components/Login/Login";
import Dashboard from "../components/Dashboard/Dashboard";
import PageNotFound from "../components/PageNotFound/PageNotFound";
import {FC, ReactNode} from "react";
const routes: Array<{
path: string,
component: FC,
is_private: boolean
}> = [
{
path: '/',
component: Login,
is_private: false
},
{
path: '/dashboard',
component: Dashboard,
is_private: true
},
{
path: '/*',
component: PageNotFound,
is_private: false
}
];
const App: React.FC = () => {
return (
<div className="wrapper">
<h1>My App</h1>
<BrowserRouter>
<Routes>
{routes.map((route) => (
<Route path={route.path}
key={route.path}
element={route.component as } />
))}
</Routes>
</BrowserRouter>
</div>
);
}