Skip to content

Commit

Permalink
Migration docs
Browse files Browse the repository at this point in the history
  • Loading branch information
KyleAMathews committed Aug 6, 2018
1 parent 197ed0e commit 7c61690
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 40 deletions.
2 changes: 1 addition & 1 deletion docs/docs/building-apps-with-gatsby.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ exports.onCreatePage = async ({ page, actions }) => {
// page.matchPath is a special key that's used for matching pages
// only on the client.
if (page.path.match(/^\/app/)) {
page.matchPath = "/app/:path"
page.matchPath = "/app/*"

// Update the page.
createPage(page)
Expand Down
50 changes: 27 additions & 23 deletions docs/docs/gatsby-link.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,22 @@ import React from "react"
import { Link } from "gatsby"

class Page extends React.Component {
render () {
<div>
<Link
to="/another-page/"
activeStyle={{
color: 'red'
}}
innerRef={(el) => { this.myLink = el }}
>
Another page
</Link>
</div>
render() {
return (
<div>
<Link
to="/another-page/"
activeStyle={{
color: "red",
}}
innerRef={el => {
this.myLink = el
}}
>
Another page
</Link>
</div>
)
}
}
```
Expand All @@ -66,23 +70,23 @@ Note that `push` was previously named `navigateTo`. `navigateTo` is deprecated i
## Prefixed paths helper

It is common to host sites in a sub-directory of a site. Gatsby let's you [set
the path prefix for your site](/docs/path-prefix/). After doing so, Gatsby's `<Link>` component will automatically handle constructing the correct URL in development and production.
the path prefix for your site](/docs/path-prefix/). After doing so, Gatsby's `<Link>` component will automatically handle constructing the correct URL in development and production.

For pathnames you construct manually, there's a helper function, `withPrefix` that prepends your path prefix in production (but doesn't during development where paths don't need prefixed).

```jsx
import { withPrefix } from "gatsby-link";
import { withPrefix } from "gatsby-link"

const IndexLayout = ({ children, location }) => {
const isHomepage = location.pathname === withPrefix("/");
const isHomepage = location.pathname === withPrefix("/")

return (
<div>
<h1>Welcome {isHomepage ? "home" : "aboard"}!</h1>
{children()}
</div>
);
};
)
}
```

## Use `<Link>` only for internal links!
Expand All @@ -100,28 +104,28 @@ question, you may need to customize the heuristic to your environment, but the
following may be a good starting point:

```jsx
import {Link as GatsbyLink} from "gatsby";
import { Link as GatsbyLink } from "gatsby"

const Link = ({ children, to, ...other }) => {
// Tailor the following test to your environment.
// This example assumes that any internal link (intended for Gatsby)
// will start with exactly one slash, and that anything else is external.
const internal = /^\/(?!\/)/.test(to);
const internal = /^\/(?!\/)/.test(to)

// Use gatsby-link for internal links, and <a> for others
if (internal) {
return (
<GatsbyLink to={to} {...other}>
{children}
</GatsbyLink>
);
)
}
return (
<a href={to} {...other}>
{children}
</a>
);
};
)
}

export default Link;
export default Link
```
181 changes: 181 additions & 0 deletions docs/docs/migrating-from-v1-to-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ This is a reference for upgrading your site from Gatsby v1 to Gatsby v2. While t
- [Convert to either pure CommonJS or pure ES6](#convert-to-either-pure-commonjs-or-pure-es6)
- [Move Babel configuration](#move-babel-configuration)
- [Restore v1 PostCSS plugin setup](#restore-v1-post-css-setup)
- [Migrate from React Router` to @reach/router](#migrate-from-react-router-to-reachrouter)
- [APIs onPreRouteUpdate and onRouteUpdate no longer called with the route update action](#apis-onprerouteupdate-and-onrouteupdate-no-longer-called-with-the-route-update-action)
- [Browser API `relaceRouterComponent` was removed](#browser-api-relaceroutercomponent-was-removed)
- [Don't query nodes by ID](#dont-query-nodes-by-id)
- [Typography.js Plugin Config](#typographyjs-plugin-config-changes)

Expand Down Expand Up @@ -349,6 +352,184 @@ module.exports = () => ({
})
```

### Migrate from React Router to @reach/router

We switched our router from [React Router v4](https://reacttraining.com/react-router/) to [@reach/router](https://reach.tech/router) as @reach/router is smaller and most importantly, has 1st class support
for accessibility.

@reach/router is written by [Ryan Florence](https://twitter.com/ryanflorence), who was also the founder of React Router. He says @reach/router restores
things he misses from React Router v3 while retaining the best parts of React Router v4 _and_ adds full accessibility support.

For _most_ sites, this change won't cause any breaking changes as the two routers are quite similar.

Two common ways this change _might_ break your site is:

- You use the object form of the `to` prop in the `<Link>` component
- You have client side routes

Read more about the features of our new router at https://reach.tech/router

Read on for instructions on migrating your site to @reach/router.

#### Only string `to` allowed

React Router allowed you to pass objects to the `to` prop e.g.

```jsx
<Link
to={{ pathname: `/about/`, search: `fun=true&pizza=false`, hash: `people` }}
>
Our people
</Link>
```

React Router would then simply concatenate the object values together into the full pathname e.g. `/about/?fun=true&pizza=false#people`.

Now you'll need to concatenate together the full pathname yourself.

```diff
- <Link to={{ pathname: `/about/`, search: `fun=true&pizza=false`, hash: `people`}}>Our people</Link>
+ <Link to={`/about/?fun=true&pizza=false#people`}>Our people</Link>
```

#### Pass state to the `state` prop

Previously with React Router to pass state to a link, you would pass it as part of a `to` object prop.

Now, to add state to a link, pass it via a `state` prop.

```jsx
const NewsFeed = () => (
<div>
<Link to="photos/123" state={{ fromNewsFeed: true }} />
</div>
)

const Photo = ({ location, photoId }) => {
if (location.state.fromFeed) {
return <FromFeedPhoto id={photoId} />
} else {
return <Photo id={photoId} />
}
}
```

#### The following props are no longer available on `<Link>`

- `exact`
- `strict`
- `location`

`exact` and `strict` are no longer necessary as @reach/router does matching
this way by default.

You could pass `location` previously to manually compute whether the
link is active or not. For advanced link stylings, use `getProps` now.

#### Use `getProps` for advanced link styling

Gatsby's `<Link>` component supports out-of-the-box `activeClassName` and `activeStyle`.

If you have more advanced styling needs, [use the `getProps` prop](https://reach.tech/router/api/Link).

#### Change client paths to use a spat

When creating a client route in `gatsby-node.js`, use a `*` to select all child routes instead of `:path`.

```diff
exports.onCreatePage = async ({ page, actions }) => {
const { createPage } = actions

// page.matchPath is a special key that's used for matching pages
// only on the client.
if (page.path.match(/^\/app/)) {
- page.matchPath = "/app/:path"
+ page.matchPath = "/app/*"

// Update the page.
createPage(page)
}
}
```

#### Migrating React Router client routes to @reach/router

- Use `<Location>` instead of `withRouter`
- import `{ navigate }` from `@reach/router` for programmatic navigation instead of the history object
- There's no `Route` component any more. You add a `<Router>` component (a site can have as many routers as it wishes) and then the immediate children of `<Router>` must have a prop named `path`.

A basic example of the `<Router>` component:

```jsx
import React from "react"
import { Router } from "@reach/router"

export default () => (
<Router>
<div path="/">I am the home!</div>
<div path="/about">Here's a bit about me</div>
<div path="/store">Buy my t-shirts!</div>
</Router>
)
```
Here's a more complex example of migrating a `<PrivateRoute>` component (used
in store.gatsbyjs.org) from React Router to @reach/router.

```diff
import React from 'react';
-import { Redirect, Route } from 'react-router-dom';
+import { Router, navigate } from '@reach/router';
import { isAuthenticated } from '../../utils/auth';
-export default ({ component: Component, ...rest }) => (
- <Route
- {...rest}
- render={props =>
- !isAuthenticated() ? (
- // If we’re not logged in, redirect to the home page.
- <Redirect to={{ pathname: '/login' }} />
- ) : (
- <Component {...props} />
- )
- }
- />
-);
+export default ({ component: Component, ...rest }) => {
+ if (!isAuthenticated() && window.location.pathname !== `/login`) {
+ // If we’re not logged in, redirect to the home page.
+ navigate(`/app/login`);
+ return null;
+ }
+
+ return (
+ <Router>
+ <Component {...rest} />
+ </Router>
+ );
+};
```

Here's links to diffs for three sites with client routes that were upgraded to @reach/router
- [store.gatsbyjs.org](https://github.com/gatsbyjs/store.gatsbyjs.org/pull/111)
- [client-only-routes](https://github.com/gatsbyjs/gatsby/pull/6918/files#diff-69757e54875e28ef83eb8efe45a33fdf)
- [simple-auth](https://github.com/gatsbyjs/gatsby/pull/6918/files#diff-53ac112a4b2ec760b26a86c953df2339)
### APIs `onPreRouteUpdate` and `onRouteUpdate` no longer called with the route update action
React Router v4 would tell us the "action" (push/replace) that trigger the route
transition. We passed this as one of the arguments along with `location` to plugins. @reach/router doesn't support this so we've removed it from the API calls.
### Browser API `relaceRouterComponent` was removed
React Router allowed you to swap out its history object. To enable this in Gatsby, an API, `replaceRouterComponent` was added so that you could use a custom version of history or React Router. As @reach/router doesn't support this, we've removed this API.
We did, erroneously, suggest using this API for adding support for Redux, etc. where you need to wrap the root Gatsby component with your own component.
If you were using `replaceRouterComponent` for this, you'll need to migrate to
`wrapRootComponent`. See this PR migrating the `using-redux` example site as a pattern to follow https://github.com/gatsbyjs/gatsby/pull/6986

### Don't query nodes by ID
Source and transformer plugins now use UUIDs for IDs. If you used glob or regex to query nodes by id then you'll need to query something else.
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorial/part-one/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Open the file at `/src/pages/index.js`. The code in this file creates a componen

> 💡 Gatsby uses **hot reloading** to speed up your development process. Essentially, when you’re running a Gatsby development server, the Gatsby site files are being “watched” in the background — any time you save a file, your changes will be immediately reflected in the browser. You don’t need to hard refresh the page, or restart the development server — your changes just appear.
2. Let’s make our changes a little more visible. Try replacing the code in `/src/pages/index.js` with the code below, and save again. You’ll see changes to the text; The text color will be purple, and the font size will be larger.
2. Let’s make our changes a little more visible. Try replacing the code in `/src/pages/index.js` with the code below, and save again. You’ll see changes to the text; The text color will be purple, and the font size will be larger.

```jsx
import React from "react"
Expand Down
2 changes: 1 addition & 1 deletion examples/client-only-paths/src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "./main.css"
const App = () => (
<div className="app">
<nav className="nav">
<Link to="/">Page 1</Link> <Link to="page/2">Page 2</Link>{" "}
<Link to="/">Page 1</Link> <Link to="page/2">Page 2</Link>{` `}
<Link to="page/3">Page 3</Link> <Link to="page/4">Page 4</Link>
</nav>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ exports.onCreatePage = ({ page, store, actions }, { prefixes }) => {
const path = page.path.match(/\/$/) ? page.path : `${page.path}/`

if (path.match(re[prefix])) {
page.matchPath = prefix.replace(/\*$/, `:path`)
page.matchPath = prefix.replace(/\*$/, `*`)
createPage(page)
return true
}
Expand Down
14 changes: 7 additions & 7 deletions packages/gatsby/cache-dir/parse-path.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
export default function parsePath(path) {
var pathname = path || "/"
var search = ""
var hash = ""
var pathname = path || `/`
var search = ``
var hash = ``

var hashIndex = pathname.indexOf("#")
var hashIndex = pathname.indexOf(`#`)
if (hashIndex !== -1) {
hash = pathname.substr(hashIndex)
pathname = pathname.substr(0, hashIndex)
}

var searchIndex = pathname.indexOf("?")
var searchIndex = pathname.indexOf(`?`)
if (searchIndex !== -1) {
search = pathname.substr(searchIndex)
pathname = pathname.substr(0, searchIndex)
}

return {
pathname: pathname,
search: search === "?" ? "" : search,
hash: hash === "#" ? "" : hash,
search: search === `?` ? `` : search,
hash: hash === `#` ? `` : hash,
}
}
9 changes: 6 additions & 3 deletions www/src/templates/template-starter-showcase.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ class StarterTemplate extends React.Component {
}}
>
{starterShowcase.owner.login}
</a>{` `}
</a>
{` `}
<span>/</span>
<div>
<h1 css={{ margin: 0, display: `inline-block` }}>
Expand All @@ -118,7 +119,8 @@ class StarterTemplate extends React.Component {
<span css={{ marginLeft: 20 }}>
<span role="img" aria-label="star">
</span>{` `}
</span>
{` `}
{starterShowcase.stars}
</span>
</div>
Expand Down Expand Up @@ -367,7 +369,8 @@ class StarterTemplate extends React.Component {
{` `}
<a href={`https://npm.im/${dep}`}>
<FaExtLink />
</a>{` `}
</a>
{` `}
{dep}
</div>
)
Expand Down
Loading

0 comments on commit 7c61690

Please sign in to comment.