Next.js: Cannot read property 'prefetch' and 'push' of null

Created on 5 Sep 2020  Â·  13Comments  Â·  Source: vercel/next.js

Bug report

Cannot read property 'prefetch' and 'push' of null

This bug starts coming when I updated the next version from 9.1.4 to 9.5.2 for both production and dev build.

Describe the bug

Cannot read property 'prefetch' of null
Cannot read property 'push' of null

Uncaught TypeError: Cannot read property 'prefetch' of null
    at prefetch (link.tsx?5e4b:98)
    at eval (link.tsx?5e4b:279)
    at eval (link.tsx?5e4b:60)
    at Array.forEach (<anonymous>)
    at IntersectionObserver.rootMargin (link.tsx?5e4b:51)
link.tsx?5e4b:144 Uncaught TypeError: Cannot read property 'push' of null
    at linkClicked (link.tsx?5e4b:144)
    at onClick (link.tsx?5e4b:314)
    at HTMLUnknownElement.callCallback (react-dom.development.js?61bb:336)
    at Object.invokeGuardedCallbackDev (react-dom.development.js?61bb:385)
    at invokeGuardedCallback (react-dom.development.js?61bb:440)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js?61bb:454)
    at executeDispatch (react-dom.development.js?61bb:584)
    at executeDispatchesInOrder (react-dom.development.js?61bb:606)
    at executeDispatchesAndRelease (react-dom.development.js?61bb:713)
    at executeDispatchesAndReleaseTopLevel (react-dom.development.js?61bb:722)
    at forEachAccumulated (react-dom.development.js?61bb:694)
    at runEventsInBatch (react-dom.development.js?61bb:739)
    at runExtractedPluginEventsInBatch (react-dom.development.js?61bb:880)
    at handleTopLevel (react-dom.development.js?61bb:5803)
    at batchedEventUpdates$1 (react-dom.development.js?61bb:24401)
    at batchedEventUpdates (react-dom.development.js?61bb:1415)
    at dispatchEventForPluginEventSystem (react-dom.development.js?61bb:5894)
    at attemptToDispatchEvent (react-dom.development.js?61bb:6010)
    at dispatchEvent (react-dom.development.js?61bb:5914)
    at unstable_runWithPriority (scheduler.development.js?3069:697)
    at runWithPriority$2 (react-dom.development.js?61bb:12149)
    at discreteUpdates$1 (react-dom.development.js?61bb:24417)
    at discreteUpdates (react-dom.development.js?61bb:1438)
    at dispatchDiscreteEvent (react-dom.development.js?61bb:5881)

To Reproduce

it's coming when Link Tag is used in the Popover element (https://react-bootstrap-v3.netlify.app/components/popovers/)

 <OverlayTrigger
    overlay={(
      <Popover id="popover-saved-item">
        <Link href="/shopping-cart">
          <a><h5>Your Saved Items wishlist</h5></a>
        </Link>
      </Popover>
      )}
  >
Click Popover
  </OverlayTrigger>

Click on

Expected behavior

the error should not be there.

Screenshots

image

System information

  • Version of Next.js: [e.g. 9.5.2]
  • Version of Node.js: [e.g. 10.16.0]

Additional context

When I add prefetch={false} to link then the prefetch error doesn`t come while rendering
but push error is still there on click of the Link

good first issue story

Most helpful comment

@Clement-Bresson
Using import { RouterContext } from 'next/dist/next-server/lib/router-context'; ends up with this error for me:

No router instance found.
You should only use "next/router" inside the client side of your app.

Note: I am using import { render } from '@testing-library/react'; instead of ReactDOM.render... from your example.

+1, experiencing all of the above issues when combining React Testing Library and the Link component. Having to fall back on Cypress, which is suboptimal for integration tests IMO.

All 13 comments

I had the same issue. But i also had a backlog thing to update my "react-tiny-popover" (from 3 to 5). After i updated it (and fixed the breaking changes) this also seems to have been fixed.

Sounds like the context value is not passed through correctly in the external component you're using.

Will fix it :)

I've been getting the same issue since v9.5(.0?) but with using sweetalert2-react-content v3.1.0

I've been getting this error in my react-testing-library tests with v9.5 where I am using in the RouterContext

...
import { render } from '@testing-library/react';
import Router from 'next/router';
import { RouterContext } from 'next-server/dist/lib/router-context';
...
test('when I click the logo, I am taken to the home page', () => {
  const { getByTestId } = render(
    <RouterContext.Provider value={Router}>
      <Header />
    </RouterContext.Provider>,
  );
...
// trigger Link to be clicked -> "Cannot read property 'push' of null" error

I don't have the same error with 9.4.4

Seeing the same thing as soon as I install Next 9.5.3. For me, calling .simulate('click') on a Next link causes this error, but not on a standard anchor tag. See below:

  it('is a test', () => {
    const testSimulate = jest.fn();

    const link = mount(
      <Link href="/test" as="/test" prefetch>
        <a onClick={testSimulate}>test</a>
      </Link>
    );

    const anchor = link.find('a').at(0);

    act(() => {
      anchor.simulate('click');
    });
    expect(testSimulate).toHaveBeenCalled();
  });

output:

Summary of all failing tests
 FAIL  __tests__/components/utilities/TrackingLink.test.js (10.554s)
   <TrackingLink /> › is a test

    Error: Uncaught [TypeError: Cannot read property 'push' of null]

       97 |
       98 |     act(() => {
    >  99 |       anchor.simulate('click');
          |              ^
      100 |     });
      101 |     expect(testSimulate).toHaveBeenCalled();
      102 |   });

conversely, using a standard anchor tag:

  it('is a test', () => {
    const testSimulate = jest.fn();

    const link = mount(<a onClick={testSimulate}>test</a>);

    act(() => {
      link.simulate('click');
    });
    expect(testSimulate).toHaveBeenCalled();
  });

works fine. I dug into the entire stack trace and can't find a single call to .push(), which is probably the most baffling part to me.

I've been getting this error in my react-testing-library tests with v9.5 where I am using in the RouterContext

...
import Router from 'next/router';
import { RouterContext } from 'next-server/dist/lib/router-context';
...
test('when I click the logo, I am taken to the home page', () => {
  const { getByTestId } = render(
    <RouterContext.Provider value={Router}>
      <Header />
    </RouterContext.Provider>,
  );
...
// trigger Link to be clicked -> "Cannot read property 'push' of null" error

I don't have the same error with 9.4.4

I'm facing the same issue here @mikerid94

I experience the same error TypeError: Cannot read property 'push' of null

Not sure why though. It seems like sometimes router passed to linkClicked function in null here
I will try to dig into it.

[Edit]. I found that the link which triggers the bug, in my case, is located inside a ReactDOM.render (I parse some content and insert some React component in the middle of some elements, maybe I would need to do this differently but that's another story). And it seems inside this rendered component Next context is indeed not passed (or at least the router). Is there a way to manually give the router context for the next link inside to work ? (I found solution below to this question)

[Edit 2] @juliosampaio @mikerid94 I tried to pass the context as you are doing, but found that error is still hapenning because the Context is not the same. So in the link when router is grabbed from useRouter, it's still empty. Using RouterContext from next/dist/next-server/lib/router-context instead of from next-server/dist/lib/router-context worked for me. So edited solution working for me:

...  
import Router from 'next/router';  
import { RouterContext } from  'next/dist/next-server/lib/router-context';  
...  
ReactDOM.render(  
  <RouterContext.Provider value={Router}>  
     <Link /> // nextJS link  
   </RouterContext.Provider>  
 someElement  
)
...

// trigger Link to be clicked -> Working

It might help some people

@Clement-Bresson
Using import { RouterContext } from 'next/dist/next-server/lib/router-context'; ends up with this error for me:

No router instance found.
You should only use "next/router" inside the client side of your app.

Note: I am using import { render } from '@testing-library/react'; instead of ReactDOM.render... from your example.

I was able to work around the issue by mocking next/link instead of next/router:

jest.mock('next/link', () => ({ children }) => children);

I experience the same error TypeError: Cannot read property 'push' of null

Not sure why though. It seems like sometimes router passed to linkClicked function in null here
I will try to dig into it.

[Edit]. I found that the link which triggers the bug, in my case, is located inside a ReactDOM.render (I parse some content and insert some React component in the middle of some elements, maybe I would need to do this differently but that's another story). And it seems inside this rendered component Next context is indeed not passed (or at least the router). Is there a way to manually give the router context for the next link inside to work ? (I found solution below to this question)

[Edit 2] @juliosampaio @mikerid94 I tried to pass the context as you are doing, but found that error is still hapenning because the Context is not the same. So in the link when router is grabbed from useRouter, it's still empty. Using RouterContext from next/dist/next-server/lib/router-context instead of from next-server/dist/lib/router-context worked for me. So edited solution working for me:

...  
import Router from 'next/router';  
import { RouterContext } from  'next/dist/next-server/lib/router-context';  
...  
ReactDOM.render(  
  <RouterContext.Provider value={Router}>  
     <Link /> // nextJS link  
   </RouterContext.Provider>  
 someElement  
)
...

// trigger Link to be clicked -> Working

It might help some people

I can confirm it worked for me as well @Clement-Bresson , thanks!

@Clement-Bresson
Using import { RouterContext } from 'next/dist/next-server/lib/router-context'; ends up with this error for me:

No router instance found.
You should only use "next/router" inside the client side of your app.

Note: I am using import { render } from '@testing-library/react'; instead of ReactDOM.render... from your example.

+1, experiencing all of the above issues when combining React Testing Library and the Link component. Having to fall back on Cypress, which is suboptimal for integration tests IMO.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pie6k picture pie6k  Â·  3Comments

jesselee34 picture jesselee34  Â·  3Comments

renatorib picture renatorib  Â·  3Comments

timneutkens picture timneutkens  Â·  3Comments

sospedra picture sospedra  Â·  3Comments