I am starting out a new react-typescript
project and I am using react-router-dom
to manage routing but I am running into the following error in the browser counter:
Matched leaf route at location "/restaurant" does not have an element. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page
Here's the code:
<BrowserRouter>
<SiteNav hasItemInCart={false} numberOfItemsInCart={0}/>
<Routes>
<Route path="/home" children={Home} />
<Route path="/restaurant" children={Restaurant} />
<Route path="/hostel" children={Hostel} />
</Routes>
</BrowserRouter>
export default class Home extends Component<any, any> {
render() {
return (
<>
<div>
Home
</div>
</>
)
}
}
class Hostel extends React.Component<any, any> {
render() {
return (
<div className="Hostal">
<body>Hostal</body>
</div>
);
}
}
As I understand it I am suppose to return a JSX.element
but typescript is throwing errors when I try to use it. Why can't I use React.Component
? How should I do this instead?
CodePudding user response:
JSX.Element
is the type of already rendered JSX. For example:
const a: JSX.Element = <>asd</>
const b: JSX.Element = <SomeComponent />
React.Component
is the type of a component that knows how to produce a JSX.Element
when rendered with specific props.
function A() { return <>Testing</> } // A is a component
const a: JSX.Element = <A />
Typically, children
in React is a JSX.Element
that you pass as the contents of a tag.
<A>
<div>children go here</div>
</A>
Or you can use the children
prop explicitly:
<A children={<div>children go here</div>} />
So in your case, you are passing a component to a prop that expects rendered content.
If you want to pass in rendered content, you want either:
<Route path="/home" children={<Home />} />
Or:
<Route path="/home"><Home/></Route>
Though modern version of react router recommend passing JSX to the element
prop. So use this unless you're on an older version.
<Route path="/home" element={<Home />} />
CodePudding user response:
I think you are mixing up React types and the Route
component API. In react-router-dom@6
there is now only an element
prop (no component
or render
/children
function props) taking a React.ReactNode
, .a.k.a. any valid JSX.
declare function Route( props: RouteProps ): React.ReactElement | null; interface RouteProps { caseSensitive?: boolean; children?: React.ReactNode; element?: React.ReactNode | null; index?: boolean; path?: string; }
You are passing your routed components to the Route
using the RRDv5 Route
component API/syntax. Convert your routes to use the element
prop.
Example:
<BrowserRouter>
<SiteNav hasItemInCart={false} numberOfItemsInCart={0} />
<Routes>
<Route path="/home" element={<Home />} />
<Route path="/restaurant" element={<Restaurant />} />
<Route path="/hostel" element={<Hostel />} />
</Routes>
</BrowserRouter>
CodePudding user response:
What version of react-router-dom is in your package.json
?
This could be a versioning problem, on react-router-dom v6 all the routes are paired like this
[props.path]: [props.element]
That means, for example, for rendering a "hey" in a "/" path
<Route path="/" element={<div>Hey!</div>} />
In your case, you'd have to invoke for restaurants
your <Restaurants />
component
<Route path="/" element={<Restaurants />} />