admin管理员组

文章数量:1419666

I am using Next.js (10.2) and Material-UI (MUI) with Typescript and having a custom Link ponent:

Link.tsx (/ponents)

import React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { withRouter } from 'next/router';
import NextLink from 'next/link';
import MuiLink from '@material-ui/core/Link';

function NextComposed(props) {
  const { as, href, prefetch, forwardedRef, ...other } = props;

  return (
    <NextLink href={href} prefetch={prefetch} as={as}>
      <a {...other} ref={forwardedRef} />
    </NextLink>
  );
}

NextComposed.propTypes = {
  as: PropTypes.string,
  href: PropTypes.string.isRequired,
  prefetch: PropTypes.bool,
  forwardedRef: PropTypes.any.isRequired,
  children: PropTypes.node.isRequired,
}

const NextComposedWithRef = React.forwardRef((props, ref) => <NextComposed {...props} forwardedRef={ref} />)

// A styled version of the Next.js Link ponent:
// 
function Link(props) {
  const { activeClassName, router, className: classNameProps, naked, ...other } = props;

  const className = clsx(classNameProps, {
    [activeClassName]: router.pathname === props.href && activeClassName,
  });

  if (naked) {
    return <NextComposed className={className} {...other} />;
  }

  return <MuiLink ponent={NextComposedWithRef} className={className} {...other} />
}

Link.propTypes = {
  activeClassName: PropTypes.string,
  as: PropTypes.string,
  className: PropTypes.string,
  href: PropTypes.string,
  naked: PropTypes.bool,
  onClick: PropTypes.func,
  prefetch: PropTypes.bool,
  router: PropTypes.shape({
    pathname: PropTypes.string.isRequired,
  }).isRequired,
  children: PropTypes.node.isRequired,
};

Link.defaultProps = {
  activeClassName: 'active',
};

export default withRouter(Link)

I also have another version of it, and it works fine. But the problem is not with the Link itself, but when I am trying to create another ponent which is containing my Link, I have the following error:

CharacterButtons.tsx

type characterButtons {
  name: string
}

const CharacterButtons: FC<characterButtons> = ({ name }) => {
  const classes = useStyles();
  return (
    <Fragment>
      <Grid
        container
        direction="row"
        justify="flex-start"
        alignItems="center"
      >
        <Link href={`/${name}`} prefetch={false}>
          <Avatar variant="square" src={`./test.png`} className={classes.large}/>
        </Link>
      </Grid>
    </Fragment>
  )
};

export default CharacterButtons;

As I understand it, it's somehow connected with HTMLPropertyIntrinsicAttributes types and its extension, but I can't figure out how. Also, I found some way with the typing to avoid the following error, but as result, it takes me to transfer every param of parent FC to my Link, like:

<Link href={`/${name}`} prefetch={false} ...{parent-props}>

I am using Next.js (10.2) and Material-UI (MUI) with Typescript and having a custom Link ponent:

Link.tsx (/ponents)

import React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { withRouter } from 'next/router';
import NextLink from 'next/link';
import MuiLink from '@material-ui/core/Link';

function NextComposed(props) {
  const { as, href, prefetch, forwardedRef, ...other } = props;

  return (
    <NextLink href={href} prefetch={prefetch} as={as}>
      <a {...other} ref={forwardedRef} />
    </NextLink>
  );
}

NextComposed.propTypes = {
  as: PropTypes.string,
  href: PropTypes.string.isRequired,
  prefetch: PropTypes.bool,
  forwardedRef: PropTypes.any.isRequired,
  children: PropTypes.node.isRequired,
}

const NextComposedWithRef = React.forwardRef((props, ref) => <NextComposed {...props} forwardedRef={ref} />)

// A styled version of the Next.js Link ponent:
// https://nextjs/docs/#with-link
function Link(props) {
  const { activeClassName, router, className: classNameProps, naked, ...other } = props;

  const className = clsx(classNameProps, {
    [activeClassName]: router.pathname === props.href && activeClassName,
  });

  if (naked) {
    return <NextComposed className={className} {...other} />;
  }

  return <MuiLink ponent={NextComposedWithRef} className={className} {...other} />
}

Link.propTypes = {
  activeClassName: PropTypes.string,
  as: PropTypes.string,
  className: PropTypes.string,
  href: PropTypes.string,
  naked: PropTypes.bool,
  onClick: PropTypes.func,
  prefetch: PropTypes.bool,
  router: PropTypes.shape({
    pathname: PropTypes.string.isRequired,
  }).isRequired,
  children: PropTypes.node.isRequired,
};

Link.defaultProps = {
  activeClassName: 'active',
};

export default withRouter(Link)

I also have another version of it, and it works fine. But the problem is not with the Link itself, but when I am trying to create another ponent which is containing my Link, I have the following error:

CharacterButtons.tsx

type characterButtons {
  name: string
}

const CharacterButtons: FC<characterButtons> = ({ name }) => {
  const classes = useStyles();
  return (
    <Fragment>
      <Grid
        container
        direction="row"
        justify="flex-start"
        alignItems="center"
      >
        <Link href={`https://www.example./character/${name}`} prefetch={false}>
          <Avatar variant="square" src={`./test.png`} className={classes.large}/>
        </Link>
      </Grid>
    </Fragment>
  )
};

export default CharacterButtons;

As I understand it, it's somehow connected with HTMLPropertyIntrinsicAttributes types and its extension, but I can't figure out how. Also, I found some way with the typing to avoid the following error, but as result, it takes me to transfer every param of parent FC to my Link, like:

<Link href={`https://www.example./character/${name}`} prefetch={false} ...{parent-props}>
Share Improve this question edited May 10, 2021 at 11:53 AlexZeDim asked May 10, 2021 at 10:37 AlexZeDimAlexZeDim 4,3724 gold badges34 silver badges77 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

I found a solution at GitHub in this two snippets, I just repaste code here, but all credits goes to: herr-vogel (next/link + MUI Button) and kachar (next/link + MUI Link and next/link + MUI Button)

Link.tsx

import React, { forwardRef, Ref } from 'react'
import Link, { LinkProps } from 'next/link'
import { Link as MuiLink, LinkProps as MuiLinkProps } from '@material-ui/core'

type LinkRef = HTMLAnchorElement
type NextLinkProps = Omit<MuiLinkProps, 'href' | 'classes'> &
  Pick<LinkProps, 'href' | 'as' | 'prefetch'>

const NextLink = ({ href, as, prefetch, ...props }: LinkProps, ref: Ref<LinkRef>) => (
  <Link href={href} as={as} prefetch={prefetch} passHref>
    <MuiLink ref={ref} {...props} />
  </Link>
)

export default forwardRef<LinkRef, NextLinkProps>(NextLink)

Using:

import Link from '../Link';

where /Link is a tsx file with export default

Before Next.js 13

import NextLink from 'next/link'
import { Link } from '@mui/material';

<NextLink href="/" passHref>
  <Link>Your Link</Link>
</NextLink>

From Next.js 13

import NextLink from 'next/link'
import { Link } from '@mui/material';

<Link href="/" ponent={NextLink}>
  Your link
</Link>

本文标签: