1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

fix: Forces Link to expose the href to the child using passHref property. (#2503)

* Forces Link to exposes the href to the child using passHref property.

* tests for passHref prop of the Link

* passHref property Link documentation
This commit is contained in:
Victor Borges 2017-07-09 02:09:02 -03:00 committed by Arunoda Susiripala
parent a3495b364d
commit 6e7ac5f0ef
4 changed files with 71 additions and 3 deletions

View file

@ -27,7 +27,8 @@ export default class Link extends Component {
return null
}
]).isRequired,
shallow: PropTypes.bool
shallow: PropTypes.bool,
passHref: PropTypes.bool
}
componentWillReceiveProps (nextProps) {
@ -121,8 +122,9 @@ export default class Link extends Component {
onClick: this.linkClicked
}
// If child is an <a> tag and doesn't have a href attribute we specify it so that repetition is not needed by the user
if (child.type === 'a' && !('href' in child.props)) {
// If child is an <a> tag and doesn't have a href attribute, or if the 'passHref' property is
// defined, we specify the current 'href', so that repetition is not needed by the user
if (this.props.passHref || (child.type === 'a' && !('href' in child.props))) {
props.href = as || href
}

View file

@ -357,6 +357,21 @@ export default () => (
)
```
##### Forcing the Link to expose `href` to its child
If child is an `<a>` tag and doesn't have a href attribute we specify it so that the repetition is not needed by the user. However, sometimes, youll want to pass an `<a>` tag inside of a wrapper and the `Link` wont recognize it as a *hiperlink*, and, consequently, wont transfer its `href` to the child. In cases like that, you should define a boolean `passHref` property to the `Link`, forcing it to expose its `href` property to the child.
```jsx
import Link from 'next/link'
import Unexpected_A from 'third-library'
export default ({ href, name }) => (
<Link href={ href } passHref>
<Unexpected_A>{ name }</Unexpected_A>
</Link>
)
```
#### Imperatively
<p><details>

View file

@ -0,0 +1,27 @@
import Link from 'next/link'
const UnexpectedNestedA = () => {
const UnexpectedWrapper = (props) => {
const {href, id} = props
const safeProps = {href, id}
return (<a {...safeProps}>{props.children}</a>)
}
return UnexpectedWrapper
}
const FakeA = UnexpectedNestedA()
export default () => (
<div className='nav-pass-href-prop'>
<Link href='/nav' passHref>
<FakeA id='with-href'>Will redirect as an `a` tag</FakeA>
</Link>
<Link href='/nav'>
<FakeA id='without-href'>Will not redirect as an `a` tag</FakeA>
</Link>
<p>This is the passHref prop page.</p>
</div>
)

View file

@ -45,6 +45,30 @@ export default (context, render) => {
})
})
describe('with unexpected <a/> nested tag', () => {
it('should not redirect if passHref prop is not defined in Link', async () => {
const browser = await webdriver(context.appPort, '/nav/pass-href-prop')
const text = await browser
.elementByCss('#without-href').click()
.waitForElementByCss('.nav-pass-href-prop')
.elementByCss('p').text()
expect(text).toBe('This is the passHref prop page.')
browser.close()
})
it('should redirect if passHref prop is defined in Link', async () => {
const browser = await webdriver(context.appPort, '/nav/pass-href-prop')
const text = await browser
.elementByCss('#with-href').click()
.waitForElementByCss('.nav-home')
.elementByCss('p').text()
expect(text).toBe('This is the home.')
browser.close()
})
})
describe('with empty getInitialProps()', () => {
it('should render an error', async () => {
const browser = await webdriver(context.appPort, '/nav')