简体   繁体   中英

typescript nav and Nextjs

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;

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: 编辑导航栏调试

It seems you didn't close the paranthesis in the return statement

return (
  <header>
   ...
  </header>
)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM