I'm currently trying to restructure a webapp I made to using typescript, react, and utilizing webpack to bundle (it was previously html+typescript). After the headache of getting webpack to work with my application and to bundle my.tsx files, I am now trying to implement routing with dynamic imports, as it's a site that I will use to host multiple separate projects. I have filled in most of these files with some test data just to test it working
I'm getting a runtime error client side, like below for each component that I'm attempting to dynamically import
Uncaught Error: Element type is invalid. Received a promise that resolves to: [object Object]. Lazy element type must resolve to a class or function.
There was a wide variety of articles I tried replicating to solve the issue to no avail. I then started reading up on documentation and things still weren't clicking. As you will see below, I tried abstracting the dynamic imports to their own react components wrapped in an actual element, and that still wasn't working. I'd prefer to use react-router-dom for routing for the simple reason being I'm familiar with it, and according to external resources, this should be possible.
Index.tsx
import React, { StrictMode } from 'react';
import ReactDOM from 'react-dom/client';
import {
BrowserRouter as Router,
Route,
Routes,
Outlet
} from 'react-router-dom';
import ReactLoading from 'react-loading';
const BudgetApp = React.lazy(() => import("./HomeServer/Envelopes"));
const HomePage = React.lazy(() => import("./Home"));
function Loading() {
return (
<span>
<ReactLoading type={"bars"} color={"#51B9D3"} height={'20%'} width={'20%'} /> <br />
Loading...
</span>
)
}
function HomePageRoute() {
return (
<React.Suspense fallback={<Loading />}>
<HomePage />
</React.Suspense>
)
}
function BudgetAppRoute() {
return (
<React.Suspense fallback={<Loading />}>
<BudgetApp />
</React.Suspense>
)
}
function RouteWrapper(): React.ReactNode {
return (
<StrictMode>
<div>
<h1>Content</h1>
<Router>
<Routes>
<Route path="/" element={<AppLayout />} />
<Route index element={<HomePageRoute />} />
<Route path="/budget" element={<BudgetAppRoute />} />
</Routes>
</Router>
</div>
</StrictMode>
)
}
const AppLayout = () => {
return (
<div>
Test display
<Outlet />
</div>
)
}
const app = RouteWrapper();
const root = ReactDOM.createRoot(document.getElementById('root') as Element);
root.render(app);
Home.tsx
import React, { FunctionComponent } from 'react';
import { NavLink } from 'react-router-dom'
import styled from 'styled-components';
import Card from 'react-bootstrap/Card';
import Button from 'react-bootstrap/Button';
type project_component = {
title: string,
description: string,
status?: string,
link: string,
}
function ProjectComponent(props: project_component) {
return (
<Card className="text-center">
<Card.Header>Featured</Card.Header>
<Card.Body>
<Card.Title>{props.title}</Card.Title>
<Card.Text>
{props.description}
</Card.Text>
<NavLink to={props.link}><Button variant="primary">Open</Button></NavLink>
</Card.Body>
<Card.Footer className="text-muted">{props.status}</Card.Footer>
</Card>
);
}
function ProjestList() {
const List = styled.div`
width: 75vw;
height: 100vh;
margin: auto;
text-align: center;
`
const krogerDescription = "An app built to build off Kroger's available dataset for better real-time updates with a dedicated server to host it for my wife and I."
const budgetDescription = "An app built for viewing both high and low level reports of how our budgeting is going. Used mostly to build on my data analytics skills for reporting"
return (
<List>
<ProjectComponent title="Kroger Grocery App" description={krogerDescription} link="/grocery" status="v1 ready" />
<ProjectComponent title="Budgeting App" description={budgetDescription} link="/budget" status="v1 WIP"/>
</List>
)
}
const App = ProjestList();
export default App as unknown as FunctionComponent;
Envelopes.tsx
import {FunctionComponent} from 'react';
import React from 'react'
import ReactDOM from 'react-dom/client';
function Test(props: {hello:string}) {
return (<div>{props.hello}</div>)
}
function Body() {
return (
<div>
hello
<Test hello="jfjjf"/>
</div>
)
}
export default Body as FunctionComponent;
If it's of any use, here's the config file I have for webpack.
const path = require('path');
module.exports = {
entry: './src/Index.tsx',
mode: "development",
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: '[name].bundle.js',
chunkFilename: '[name].bundle.js',
path: path.resolve(__dirname, 'public/js'),
publicPath: 'dist/'
}
};
Y'all. I found the answer right as I finished writing this. I figured there was no way I was just gonna waste a perfectly good question for future me to stumble upon or some other unlucky soul.
It turns out, my problem lied within Home.tsx . At the bottom of the file, I called this line:
const App = ProjestList();
export default App as unknown as FunctionComponent;
Instead, I needed to export the COMPONENT... not the object returned from it. Which is funny, because in the other file I did it correctly. It should look like this:
export default ProjestList as FunctionComponent;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.