Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set up Storybook to work with Next.js's Link tag

I'm trying to set up Storybook for a Next.js project. I have a component that render the Link tag from Next.js. My problem is that when I load this component, Storybook throws the following error:

Cannot read property 'pageLoader' of null
   at Link.handleRef

What does one have to do to get Storybook working with Next.js Routing, specifically rendering the Link tag?

Update: Code that causes the error:

// button-component.js
import Link from 'next/link.js';
import t from 'prop-types';
import React from 'react';

function Button({ as, children, href, ...props }) {
  const isExternal = href && href.startsWith('http');
  const a = (
    <a href={href} {...props}>
      {children}
    </a>
  );

  if (href) {
    return isExternal ? (
      a
    ) : (
      <Link href={href} as={as}>
        {a}
      </Link>
    );
  }

  return (
    <button type="button" {...props}>
      {children}
    </button>
  );
}

Button.propTypes = {
  as: t.string,
  children: t.node,
  href: t.string,
};

export default React.memo(Button);
// button.stories.js
import React from 'react';

import Button from './button-component';

export default {
  title: 'Button',
};

export const standardButton = () => <Button>Standard Button</Button>;

export const internalLink = () => <Button href='/buy'>
  Internal Link
</Button>;

export const externalLink = () => (
  <Button target="_blank" href="https://www.hopin.to">
    External Link
  </Button>
);
like image 893
J. Hesters Avatar asked Jan 13 '20 07:01

J. Hesters


People also ask

How do I link to another JavaScript page?

When linking between pages on websites, you use the <a> HTML tag. In Next. js, you can use the Link Component next/link to link between pages in your application. <Link> allows you to do client-side navigation and accepts props that give you better control over the navigation behavior.

Does storybook work with tailwind?

Now you'll be able to add Tailwind styles to your Storybook components. Test by changing the “stories/Button. tsx” file to include a tailwind style like this (example “bg-yellow-500”).

How do I set up storybook react?

Creating a React Application To start using Storybook, you will first create a React project and then create components and their stories. This will generate a folder called btn-storybook with all the dependencies a React application needs. Next, with just a few more steps, you can install and run Storybook.


1 Answers

I found an issue reported about this on Next.js's github: https://github.com/zeit/next.js/issues/9951

It was reported only 5 days ago, so you could be having the same issue. The resolution is to upgrade to nextjs v9.1.8-canary.6. Reading more about this and looking at the source code, this is likely your problem. Also, there are more recent canary builds of nextjs, if you want to try something newer.

If that doesn't resolve it, my other guess is that you're getting errors because you're using Link outside of a Next.js page. Next.js may include dependencies for pages, behind the scenes. Link may rely on those dependencies and is throwing an error when they aren't found. If you want to test your components outside of Next.js pages, you could create a custom Link component that tests whether you're in Next.js and only renders Link if you are. For example:

import Link from 'next/link'
import Router from 'next/router'

const CustomLink = ({children, ...otherProps}) => {
  const isPage = () => {
    // if we're in a next.js route, then Router.router will be set
    return Boolean(Router.router)
  }

  return isPage()
    ? (<Link {...otherProps}>{children}</Link>)
    : children
}

Then use CustomLink instead of Link.

like image 133
Cully Avatar answered Oct 17 '22 14:10

Cully