I'm learning typescript and I'm trying to build a navigation. I'm getting x Unexpected token header
. Expected jsx identifier
,----
25 |
I don't know what to make of this. Can someone advise as to where the issue might be?
Navbar.tsx file:
import Link from "next/link";
import React, { useState } from "react";
import NavItem from "./NavItem";
export interface INavbar {
navActive: boolean;
}
//export function Navbar(props: INavbar) {
const Navbar: React.FC<INavbar> = (className, ...navProps) => {
const [navActive, setNavActive] = useState(null);
const [activeIdx, setActiveIdx] = useState(-1);
const MENU_LIST :{ text: string, href: string}[] = [
{ text: "Home", href: "/" },
{ text: "About Us", href: "/about" },
{ text: "Contact", href: "/contact" },
];
return (
<header>
<nav className={`nav`}>
<Link href={"/"}>
<a>
<h1 className="logo">KT</h1>
</a>
</Link>
<div
onClick={() => setNavActive(!navActive)}
className={`nav__menu-bar`}
>
</div>
<div className={`${navActive ? "active" : ""} nav__menu-list`}>
{MENU_LIST.map((menu, idx) => (
<div
onClick={() => {
setActiveIdx(idx);
setNavActive(false);
}
key={menu.text}
>
<NavItem active={activeIdx === idx} {...menu} />
</div>
)
</div>
</nav>
</header>
}
export default Navbar;
Navitem.tsx file:
import Link from 'next/link';
//Create a functional component with text, href and active as props and use Link from next/link to link pages
export interface INavItem {
text: string;
href: string;
active: boolean;
}
const NavItem: React.FC<INavItem> = ({ text, href, active }) => {
return (
<Link href={href}>
<a className={`nav__item ${active ? 'active' : ''}`}>{text}</a>
</Link>
);
};
export default NavItem;
CodePudding user response:
You seem to be missing some parenthesis/brackets. Your Navbar should look like this:
}} <--- Added a bracket here
key={menu.text}
>
<NavItem active={activeIdx === idx} {...menu} />
</div>
))} <--- Added a parenthesis and a bracket
</div>
</nav>
</header>
)} <--- Added a parenthesis
One more issue is that the props passed to a component are passed as a single object, but in Navbar
they are being used as if multiple objects were passed in.
Try changing:
const Navbar: React.FC<INavbar> = (className, ...navProps) => {
to:
const Navbar: React.FC<INavbar> = ({className, ...navProps}) => {
Now we are properly using the interface INavbar
, but className
is not expected in INavbar
, so we need to either add className
to INavbar
or remove it from the props destructuring assignment. In this case, className
is not being used anywhere, so we can remove it:
const Navbar: React.FC<INavbar> = ({...navProps}) => {
We are using navActive
, but we are not using navProps
anywhere, so we can further adjust what props are being destructured:
const Navbar: React.FC<INavbar> = ({ navActive }) => {
It looks like you are trying to use navActive as a props, and you are also defining it with useState
... You can only do one or the other since navActive
can't be both a state variable and a prop.
I'm guessing you want to pass it in as a prop, so the next instructions will be based on that assumption. In that case, we can go ahead and remove this line:
const [navActive, setNavActive] = useState(null);
Now we are getting the error Cannot find name 'setNavActive'
. We'll need to define setNavActive
, and since navActive
is being passed in as a props, we'll have setNavActive
also be passed in as a prop:
export interface INavbar {
navActive: boolean;
setNavActive: (value: boolean) => void;
}
const Navbar: React.FC<INavbar> = ({ navActive, setNavActive }) => {
Notice we set the type of setNavActive
to be (value: boolean) => void
in our INavBar
. This means setNavActive
is a function which expects one parameter of type boolean
(called value).
Since we added setNavActive
as an expected prop, Typescript now helps us out by telling us where <Navbar />
is used that Property 'setNavActive' is missing
.
Wherever you are using Navbar
, we now need to make sure we are passing in navActive
and setNavActive
as props like this:
<Navbar navActive={navActive} setNavActive={setNavActive} />
In that same component we also want to define navActive
and setNavActive
using useState
. We will initialize navActive
to false
, since we defined navActive
as a boolean:
const [navActive, setNavActive] = useState(false);
That is a lot of instructions, but I hope it was helpful. It may be useful to look at all of my suggestions applied at once, so I've created a full example on CodeSandbox where you can see everything working:
CodePudding user response:
It seems you didn't close the paranthesis in the return statement
return (
<header>
...
</header>
)