Skip to content

Commit cb11c7c

Browse files
committed
add Link component
1 parent 66b224a commit cb11c7c

File tree

3 files changed

+78
-8
lines changed

3 files changed

+78
-8
lines changed

client/eval-script.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import React from 'react'
22
import ReactDOM from 'react-dom'
33
import App from '../lib/app'
4+
import Link from '../lib/link'
45

56
const modules = new Map([
67
['react', React],
78
['react-dom', ReactDOM],
8-
['next/app', App]
9+
['next/app', App],
10+
['next/link', Link]
911
])
1012

1113
/**

lib/link.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import React, { Component, PropTypes, Children } from 'react'
2+
3+
export default class Link extends Component {
4+
static contextTypes = {
5+
router: PropTypes.object
6+
}
7+
8+
constructor (props) {
9+
super(props)
10+
this.linkClicked = this.linkClicked.bind(this)
11+
}
12+
13+
linkClicked (e) {
14+
if ('A' === e.target.nodeName &&
15+
(e.metaKey || e.ctrlKey || e.shiftKey || 2 === e.nativeEvent.which)) {
16+
// ignore click for new tab / new window behavior
17+
return
18+
}
19+
20+
const { href, scroll } = this.props
21+
22+
if (!isLocal(href)) {
23+
// ignore click if it's outside our scope
24+
return
25+
}
26+
27+
e.preventDefault()
28+
29+
// straight up redirect
30+
this.context.router.goTo(href, (err) => {
31+
if (err) {
32+
if (this.props.onError) this.props.onError(err)
33+
return
34+
}
35+
36+
if (false !== scroll) {
37+
window.scrollTo(0, 0)
38+
}
39+
})
40+
}
41+
42+
render () {
43+
const children = Children.map(this.props.children, (child) => {
44+
const props = {
45+
onClick: this.linkClicked
46+
}
47+
48+
const isChildAnchor = child && 'a' === child.type
49+
50+
// if child does not specify a href, specify it
51+
// so that repetition is not needed by the user
52+
if (!isChildAnchor || !('href' in child.props)) {
53+
props.href = this.props.href
54+
}
55+
56+
if (isChildAnchor) {
57+
return React.cloneElement(child, props)
58+
} else {
59+
return <a {...props}>{child}</a>
60+
}
61+
})
62+
63+
return children[0]
64+
}
65+
}
66+
67+
function isLocal (href) {
68+
const origin = location.origin
69+
return !/^https?:\/\//.test(href) ||
70+
origin === href.substr(0, origin.length)
71+
}

server/build.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ export function transpile (path) {
2626
moduleAlias,
2727
[
2828
{ src: `npm:${babelRuntimePath}`, expose: 'babel-runtime' },
29-
{ src: `npm:${require.resolve('react')}`, expose: 'react' }
29+
{ src: `npm:${require.resolve('react')}`, expose: 'react' },
30+
{ src: `npm:${require.resolve('../lib/link')}`, expose: 'next/link' }
3031
]
3132
]
3233
],
@@ -51,13 +52,9 @@ export function bundle (path) {
5152
externals: [
5253
'react',
5354
'react-dom',
54-
'next',
55-
'next/head',
56-
'next/link',
57-
'next/component',
58-
'next/app',
5955
{
60-
[require.resolve('react')]: 'react'
56+
[require.resolve('react')]: 'react',
57+
[require.resolve('../lib/link')]: 'next/link'
6158
}
6259
],
6360
resolveLoader: {

0 commit comments

Comments
 (0)