Material-components-web: Persistent Drawer links not working as expected with react-router-dom

Created on 24 Jul 2017  路  10Comments  路  Source: material-components/material-components-web

When mdc-web persistent drawer is used with react-router-dom (BrowserRouter), the links inside the drawer are losing SPA behavior. That is links the links (html<a>) inside the drawer are bypassing react-router, and making a fresh request to the server.

What MDC-Web Version are you using?

https://unpkg.com/material-components-web@latest/dist/material-components-web.css
https://unpkg.com/material-components-web@latest/dist/material-components-web.js

What browser(s) is this bug affecting?

Chrome

Version 59.0.3071.115 (Official Build) (64-bit)

What OS are you using?

macos sierra, and windows 10.

What are the steps to reproduce the bug?

  1. npm install -g create-react-app
  2. git clone https://github.com/smandava/router-issue
  3. cd router-issue
  4. npm i
  5. npm start
  6. open http://localhost:3000 on your browser
  7. open developer tools and network tab

    7. click on About link, network tab shows about 12 requests made to the server to render the page (actual behaviour)

  8. open app.js in a text editor.

  9. replace BrowserRouter with HashRouter and save the file.
  10. open http://localhost:3000 on your browser
  11. open developer tools and network tab
  12. click on About link, you see the No network requests but the link is still functional. (expected behaviour).

What is the expected behavior?

Described in (12) above.

What is the actual behavior?

Described in (7) above.

Any other information you believe would be useful?

None.

Most helpful comment

I had this same issue. This is my workaround until something gets implemented:

if (!MDCTemporaryDrawer.prototype.getDefaultFoundation_) {
  MDCTemporaryDrawer.prototype.getDefaultFoundation_ = MDCTemporaryDrawer.prototype.getDefaultFoundation;
  MDCTemporaryDrawer.prototype.getDefaultFoundation = function() {
    const foundation = this.getDefaultFoundation_();

    foundation.drawerClickHandler_ = (e) => {
      if (e.target.tagName !== 'A') {
        e.stopPropagation();
      }
    };

    return foundation;
  };
}

All 10 comments

CodePen of the above problem

https://codepen.io/anon/pen/LjYqom (Clicking on any navigation links take to codepen home page.)

Below is the expected behaviour

https://codepen.io/anon/pen/vJYbZR (This is using HashRouter instead of BrowserRouter)

Another CodePen with permanent drawer, where the links work as expected.

https://codepen.io/anon/pen/rzNgMO

Below are the comments from reactor-router team on the issue ..

Not a React Router issue. If you added a debugger; line to the <Link>'s cilck handler, you would see that it never gets called. It appears that MDC is attaching click handlers to your links and those are causing that navigation to happen.

The hash router only appears to work. If you look at the history, you will see that the history.action after clicking a link is POP, when it should be PUSH. The hash history attaches an onhashchange event to the window, which is why it can react to the location changes, but not correctly.

You'll have to see if you can disabled MDC's click handler because React Router links won't work if they can't use their own click handler.

( https://github.com/ReactTraining/react-router/issues/5370 )

Thanks for taking the time to file this issue, @smandava!

We would be happy to help you troubleshoot on our Discord channel 馃檪

I opened the same issue here: #644 on 14th of May! But somehow it got closed, without fixing it. @smandava In #644 you can find some ideas to workaround the issue for now.

thanks for the work around. It looks like primary issue is the foundation classes are not bubbling down the click event to child elements. In this case anchor element generated by react router Link.

I had this same issue. This is my workaround until something gets implemented:

if (!MDCTemporaryDrawer.prototype.getDefaultFoundation_) {
  MDCTemporaryDrawer.prototype.getDefaultFoundation_ = MDCTemporaryDrawer.prototype.getDefaultFoundation;
  MDCTemporaryDrawer.prototype.getDefaultFoundation = function() {
    const foundation = this.getDefaultFoundation_();

    foundation.drawerClickHandler_ = (e) => {
      if (e.target.tagName !== 'A') {
        e.stopPropagation();
      }
    };

    return foundation;
  };
}

Same issue persists with Temporary Drawer on MDC V0.21.1 generated using React's default create-react-app with react-router-dom.

above snippet by @AustP works to fix.

@AustP solution also works with MDCPersistentDrawer, just replace MDCTemporaryDrawer with MDCPersistentDrawer

This has been fixed via 3e173e1ddc3bff5c7c9c2d794eeb36a9354ec98c (based on #1138), which refactors out the stopPropagation call.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  3Comments

trimox picture trimox  路  4Comments

7iomka picture 7iomka  路  3Comments

AbuMareBear picture AbuMareBear  路  3Comments

kimurakenshi picture kimurakenshi  路  3Comments