Polaris-react: useLinkComponent with react-router-dom

Created on 15 Aug 2017  路  5Comments  路  Source: Shopify/polaris-react

Issue summary

Swapping out UnstyledLink component with react-router-dom's (router v4) doesn't appear to work (very likely to be how i'm implementing it!)

Expected behavior

All Link Components to be swapped out by react-router-dom link

Actual behavior

screen shot 2017-08-15 at 14 27 22

Steps to Reproduce the Problem

import {
  useLinkComponent
} from '@shopify/polaris';

import { BrowserRouter as Router, Route, Link } from 'react-router-dom'

useLinkComponent(Link);

Example of usage:

<ResourceList
  items={[
    {
      url: '#',     <---- this should be using UnstyledLink which is swapped out with react router's Link. 
      media: <Thumbnail
        source="https://burst.shopifycdn.com/photos/[email protected]"
        alt="Black choker necklace"
      />,
      attributeOne: 'Elegant necklace',
      attributeTwo: 'Accessory by Marcuse',
      attributeThree: '12 in stock',
    }
  ]}
  renderItem={() => {}}
/>

It does appear to be swapped; however, as per line 22 UnstyledLink.tsx it appears the url prop is getting passed to react-router-dom's component (therefore to is unset?)

Thanks for the awesome lib - Really does help with a consistent Shopify experience for customers!

Most helpful comment

Latest Polaris AppProvider component accepts a linkComponent prop that can be used with the AdapterLink example shown in this page.

https://polaris.shopify.com/components/structure/app-provider#navigation

All 5 comments

馃憢 Hello!

So you're correct that line 22 is indeed the culprit here. However, we probably won't be changing this functionality any time soon.

In our projects that consume polaris we generally use some kind of adapter component for cases like this. So, for example you might do something like:

/// in AdapterLink.jsx
import * as React from 'react';
import Link from 'react-router/lib/Link';

function AdapterLink({url, ...rest}) {
  return <Link to={url} {...rest} />;
}


// in some other file
import {
  useLinkComponent
} from '@shopify/polaris';

import AdapterLink from './AdapterLink'

useLinkComponent(AdapterLink);

This is also convenient because it lets you do any custom behaviour you might want in all your links (in our case this is mostly stuff like opening links to external domains in a new tab).

Let me know if that's a satisfactory answer and I'll close this.

I'm glad you're enjoying working with the components! 馃槃

I'm going to close this. Please feel free to re-open if there is more to add here.

@TheMallen your solution worked for URLs in my ResourceList items, but it doesn't seem to work for the URL in breadcrumbs on the Page component - they are still being treated as 'external' URLs. Do you know if I need to do something different on here?

@TheMallen I'm using the AdapterLink suggested solution, thank you !

However I think that it breaks the native compatibility of the Embedded App url history management. The ShopifyApp.pushState is supposed to be dispatched automatically : at least that's the behaviour I expect from the EASDK guide .. but it's not when using react-router v4+ and this AdapterLink solution.

Here is the workaround I created :

import { Route } from 'react-router-dom';
import {useLinkComponent} from '@shopify/polaris';

import AdapterLink from 'lib/adapter_link.js';
useLinkComponent(AdapterLink);  

function withShopifyEmbeddedAppPushState(WrappedComponent) {
  return class extends React.Component {
    static contextTypes = {
      easdk: PropTypes.object
    };

    componentWillReceiveProps(nextProps) {
      this.context.easdk.pushState(nextProps.computedMatch.url);
    }

    render () {
      return <WrappedComponent {...this.props} />;
    }
  }
}
const ShopifyEmbeddedAppRoute = withShopifyEmbeddedAppPushState(Route);

And then you can it like this :

<EmbeddedApp apiKey={"yourkey"} shopOrigin={"https://..."}>
  <BrowserRouter>
    <ShopifyEmbeddedAppRoute path="/home" component={Home} />
  </BrowserRouter>
</EmbeddedApp>

If anyone has a better / more native way I'd be interested :)

Latest Polaris AppProvider component accepts a linkComponent prop that can be used with the AdapterLink example shown in this page.

https://polaris.shopify.com/components/structure/app-provider#navigation

Was this page helpful?
0 / 5 - 0 ratings