From 41a4d269c4cfbf12948a62acbecd05ce14448cea Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Wed, 10 May 2017 23:32:42 -0700 Subject: [PATCH] Make this.props.children a function in layouts so can control which page is rendered as child --- examples/gatsbygram/gatsby-node.js | 2 +- examples/gatsbygram/src/components/modal.js | 24 ++++-- .../src/layouts/{default.js => index.js} | 57 ++++++++++--- examples/gatsbygram/src/pages/index.js | 4 +- .../gatsbygram/src/templates/post-page.js | 1 + .../src/layouts/{default.js => index.js} | 0 examples/using-drupal/src/pages/index.js | 2 +- packages/gatsby-link/src/index.js | 6 +- packages/gatsby-plugin-preact/package.json | 4 +- .../gatsby/lib/cache-dir/production-app.js | 29 ++++--- packages/gatsby/lib/cache-dir/root.js | 79 ++++++++++++------- packages/gatsby/lib/cache-dir/static-entry.js | 46 ++++------- www/src/templates/template-blog-post.js | 1 - 13 files changed, 161 insertions(+), 94 deletions(-) rename examples/gatsbygram/src/layouts/{default.js => index.js} (71%) rename examples/using-drupal/src/layouts/{default.js => index.js} (100%) diff --git a/examples/gatsbygram/gatsby-node.js b/examples/gatsbygram/gatsby-node.js index 7a71bb6a50770..f0f132c407427 100644 --- a/examples/gatsbygram/gatsby-node.js +++ b/examples/gatsbygram/gatsby-node.js @@ -54,7 +54,7 @@ exports.createPages = ({ graphql, boundActionCreators }) => { // as a template component. The `context` is // optional but is often necessary so the template // can query data specific to each page. - path: slug(edge.node.id), + path: `/${slug(edge.node.id)}/`, component: slash(postTemplate), context: { id: edge.node.id, diff --git a/examples/gatsbygram/src/components/modal.js b/examples/gatsbygram/src/components/modal.js index 619ee40fbaaf3..0833702c86fc4 100644 --- a/examples/gatsbygram/src/components/modal.js +++ b/examples/gatsbygram/src/components/modal.js @@ -1,11 +1,11 @@ import React from "react" import Modal from "react-modal" -import browserHistory from "react-router/lib/browserHistory" import CaretRight from "react-icons/lib/fa/caret-right" import CaretLeft from "react-icons/lib/fa/caret-left" import Close from "react-icons/lib/md/close" import findIndex from "lodash/findIndex" import mousetrap from "mousetrap" +import * as PropTypes from "prop-types" import { rhythm } from "../utils/typography" @@ -16,6 +16,10 @@ class GatsbyGramModal extends React.Component { posts: React.PropTypes.array.isRequired, } + static contextTypes = { + router: PropTypes.Object, + } + componentDidMount() { mousetrap.bind(`left`, () => this.previous()) mousetrap.bind(`right`, () => this.next()) @@ -51,7 +55,7 @@ class GatsbyGramModal extends React.Component { } else { nextPost = posts[currentIndex + 1] } - browserHistory.push(`/${nextPost.id}/`) + this.context.router.history.push(`/${nextPost.id}/`) } } @@ -69,15 +73,17 @@ class GatsbyGramModal extends React.Component { } else { previousPost = posts[currentIndex - 1] } - browserHistory.push(`/${previousPost.id}/`) + this.context.router.history.push(`/${previousPost.id}/`) } } render() { + console.log(this.props) + console.log("context", this.context) return ( browserHistory.push(`/`)} + onRequestClose={() => this.context.router.history.push(`/`)} style={{ overlay: { position: `fixed`, @@ -103,7 +109,7 @@ class GatsbyGramModal extends React.Component { contentLabel="Modal" >
browserHistory.push(`/`)} + onClick={() => this.context.router.history.push(`/`)} css={{ display: `flex`, position: `relative`, @@ -129,7 +135,11 @@ class GatsbyGramModal extends React.Component { }} onClick={e => this.previous(e)} /> - {this.props.children} + {console.log("rendering modal")} + {console.log(this.props.children)} + {this.props.children({ + location: { pathname: this.props.location.pathname }, + })}
browserHistory.push(`/`)} + onClick={() => this.context.router.history.push(`/`)} css={{ cursor: `pointer`, color: `rgba(255,255,255,0.8)`, diff --git a/examples/gatsbygram/src/layouts/default.js b/examples/gatsbygram/src/layouts/index.js similarity index 71% rename from examples/gatsbygram/src/layouts/default.js rename to examples/gatsbygram/src/layouts/index.js index 3678a2fed271a..52f1388d58aff 100644 --- a/examples/gatsbygram/src/layouts/default.js +++ b/examples/gatsbygram/src/layouts/index.js @@ -33,8 +33,11 @@ class DefaultLayout extends React.Component { // Cache the window width. this.windowWidth = window.innerWidth + console.log("componentDidMount", this.windowWidth) } componentWillReceiveProps(nextProps) { + console.log(this.props.children === nextProps.children) + console.log("nextProps", nextProps) // if we're changing to a non-homepage page, put things in // a modal (unless we're on mobile). if ( @@ -42,6 +45,7 @@ class DefaultLayout extends React.Component { nextProps.location.pathname !== `/about/` && this.windowWidth > 750 ) { + console.log("put things in a modal") // Freeze the background from scrolling. this.htmlElement.style.overflow = `hidden` this.bodyElement.style.overflow = `hidden` @@ -50,10 +54,19 @@ class DefaultLayout extends React.Component { // weird jumping. this.htmlElement.style.overflowY = `scroll` + this.isModal = true // Save the homepage if we haven't already. - if (!this.modalBackgroundChildren) { - this.modalBackgroundChildren = this.props.children - } + // console.log("this.modalBackgroundChildren", this.modalBackgroundChildren) + // console.log("this.props.children", this.props.children) + // if (!this.modalBackgroundChildren) { + // this.modalBackgroundChildren = nextProps.children + // this.modalBackgroundChildren = React.createElement( + // this.props.children.type.WrappedComponent, + // { + // location: { pathname: `/` }, + // } + // ) + // } } else { // Otherwise we're navigating back home so delete old home so the // modal can be destroyed. @@ -68,8 +81,25 @@ class DefaultLayout extends React.Component { } render() { + console.log(this.props.children) const { location } = this.props - const isModal = this.modalBackgroundChildren + let isModal = false + console.log(this.props.location.pathname) + console.log(this.windowWidth) + if ( + this.props.location.pathname !== `/` && + this.props.location.pathname !== `/about/` && + this.windowWidth > 750 + ) { + isModal = true + } + // const isModal = this.isModal + console.log("isModal", isModal) + // console.log("------render---------") + // console.log("render props", this.props) + console.log(location.pathname) + // console.log("modalBackgroundChildren", isModal) + // console.log("layout props", this.props) return (
- {isModal ? this.modalBackgroundChildren : this.props.children} +
+ {isModal + ? this.props.children({ + ...this.props, + location: { pathname: `/` }, + }) + : this.props.children()} +
- {isModal && - - {this.props.children} - } +
+ {isModal && + + {this.props.children} + } +
) diff --git a/examples/gatsbygram/src/pages/index.js b/examples/gatsbygram/src/pages/index.js index 9ff924c85d1fc..cd37bc51a23ac 100644 --- a/examples/gatsbygram/src/pages/index.js +++ b/examples/gatsbygram/src/pages/index.js @@ -64,6 +64,7 @@ class Index extends React.Component { } render() { + console.log(this.props) let { allPostsJson, user } = this.props.data const posts = allPostsJson.edges.map(e => e.node) @@ -128,9 +129,10 @@ class Index extends React.Component { {/* posts */} - {chunk(posts.slice(0, this.state.postsToShow), 3).map(chunk => { + {chunk(posts.slice(0, this.state.postsToShow), 3).map((chunk, i) => { return (
+

{article.created} diff --git a/packages/gatsby-link/src/index.js b/packages/gatsby-link/src/index.js index 035d828a81a80..9da558f57ad6e 100644 --- a/packages/gatsby-link/src/index.js +++ b/packages/gatsby-link/src/index.js @@ -20,9 +20,9 @@ class GatsbyLink extends React.Component { // that don't support service workers *cough* Safari/IE *cough*. // TODO also add check if user is using SW, e.g. window.caches if ( - (process.env.NODE_ENV === `production` && - !(`serviceWorker` in navigator)) || - window.location.protocol !== `https:` + process.env.NODE_ENV === `production` && + (!(`serviceWorker` in window.navigator) || + window.location.protocol !== `https:`) ) { requestUserIdle(() => { console.log(`the user is idle`) diff --git a/packages/gatsby-plugin-preact/package.json b/packages/gatsby-plugin-preact/package.json index 0bcc1566f6742..2cd4df91d0977 100644 --- a/packages/gatsby-plugin-preact/package.json +++ b/packages/gatsby-plugin-preact/package.json @@ -15,8 +15,8 @@ "author": "Kyle Mathews ", "license": "MIT", "dependencies": { - "preact": "^7.1.0", - "preact-compat": "^3.11.0" + "preact": "^8.1.0", + "preact-compat": "^3.16.0" }, "devDependencies": { "babel-cli": "^6.24.1" diff --git a/packages/gatsby/lib/cache-dir/production-app.js b/packages/gatsby/lib/cache-dir/production-app.js index 7132f5f23ed2b..17cb253251e79 100644 --- a/packages/gatsby/lib/cache-dir/production-app.js +++ b/packages/gatsby/lib/cache-dir/production-app.js @@ -4,7 +4,7 @@ apiRunner(`clientEntry`) import React from "react" import ReactDOM from "react-dom" -import { BrowserRouter as Router, Route, Switch } from "react-router-dom" +import { BrowserRouter as Router, Route, withRouter } from "react-router-dom" import { ScrollContext } from "react-router-scroll" import createHistory from "history/createBrowserHistory" import routes from "./routes.json" @@ -29,6 +29,11 @@ const loadScriptsForPath = (path, cb = () => {}) => { } const page = routes.find(r => r.path === path) + + if (!page) { + return cb() + } + console.time(`load scripts`) let scripts = { layout: false, @@ -94,11 +99,13 @@ const renderPage = props => { ...props, ...scriptsCache[props.location.pathname].pageData, }) - } else { - $(notFoundScripts.component, { + } else if (notFoundScripts) { + return $(notFoundScripts.component, { ...props, ...notFoundScripts.pageData, }) + } else { + return null } } @@ -108,7 +115,7 @@ const renderSite = ({ scripts, props }) => { const $ = React.createElement -loadScriptsForPath(window.location.pathname, () => { +loadScriptsForPath(window.location.pathname, scripts => { const Root = () => $( Router, @@ -116,12 +123,14 @@ loadScriptsForPath(window.location.pathname, () => { $( ScrollContext, { shouldUpdateScroll }, - $(Route, { - component: props => { - window.___history = props.history - return renderSite({ - scripts: scriptsCache[props.location.pathname], - props, + $(withRouter(scripts.layout), { + children: layoutProps => { + return $(Route, { + component: routeProps => { + const props = layoutProps ? layoutProps : routeProps + window.___history = props.history + return renderPage(props) + }, }) }, }) diff --git a/packages/gatsby/lib/cache-dir/root.js b/packages/gatsby/lib/cache-dir/root.js index 401608a292748..75825a2def02e 100644 --- a/packages/gatsby/lib/cache-dir/root.js +++ b/packages/gatsby/lib/cache-dir/root.js @@ -1,5 +1,10 @@ import React from "react" -import { BrowserRouter as Router, Route, Switch } from "react-router-dom" +import { + BrowserRouter as Router, + Route, + Switch, + withRouter, +} from "react-router-dom" import { ScrollContext } from "react-router-scroll" import createHistory from "history/createBrowserHistory" @@ -7,6 +12,7 @@ import apiRunner from "./api-runner-browser" // import rootRoute from "./child-routes" import syncRequires from "./sync-requires" import routes from "./routes.json" +console.log(routes) const history = createHistory() history.listen((location, action) => { @@ -36,6 +42,22 @@ const $ = React.createElement const filteredRoutes = routes.filter(r => r.path !== `/404.html`) const noMatch = routes.find(r => r.path === `/404.html`) +const addNotFoundRoute = () => { + if (noMatch) { + return $(Route, { + key: `404-page`, + component: props => + $(syncRequires.components[noMatch.componentChunkName], { + ...props, + ...syncRequires.json[noMatch.jsonName], + }), + }) + } else { + return null + } +} + +console.log("withRouter", withRouter) const Root = () => $( Router, @@ -43,35 +65,34 @@ const Root = () => $( ScrollContext, { shouldUpdateScroll }, - $(Route, { - component: props => { - window.__history = props.history - // TODO add support for multiple nested layouts - // and for layouts to be able to have their own queries. - return $( - syncRequires.layouts[`index`], - { ...props }, - $(Switch, null, [ - ...filteredRoutes.map(route => { - return $(Route, { - exact: true, - path: route.path, - component: props => - $(syncRequires.components[route.componentChunkName], { - ...props, - ...syncRequires.json[route.jsonName], - }), + $(withRouter(syncRequires.layouts[`index`]), { + children: layoutProps => { + return $(Route, { + component: routeProps => { + window.___history = routeProps.history + if (layoutProps) { + console.log("layoutProps", layoutProps.location.pathname) + } + console.log("routeProps", routeProps.location.pathname) + const props = layoutProps ? layoutProps : routeProps + console.log( + "child function props", + props, + props.location.pathname + ) + const page = routes.find( + route => route.path === props.location.pathname + ) + if (page) { + return $(syncRequires.components[page.componentChunkName], { + ...props, + ...syncRequires.json[page.jsonName], }) - }), - $(Route, { - component: props => - $(syncRequires.components[noMatch.componentChunkName], { - ...props, - ...syncRequires.json[noMatch.jsonName], - }), - }), - ]) - ) + } else { + return addNotFoundRoute() + } + }, + }) }, }) ) diff --git a/packages/gatsby/lib/cache-dir/static-entry.js b/packages/gatsby/lib/cache-dir/static-entry.js index 23855f92c2b95..b948468286908 100644 --- a/packages/gatsby/lib/cache-dir/static-entry.js +++ b/packages/gatsby/lib/cache-dir/static-entry.js @@ -1,9 +1,8 @@ import React from "react" import { renderToString, renderToStaticMarkup } from "react-dom/server" -import { StaticRouter, Switch, Route } from "react-router-dom" +import { StaticRouter, Route, withRouter } from "react-router-dom" import Html from "../src/html" import { kebabCase, get, merge } from "lodash" -import rootRoute from "./child-routes" import apiRunner from "./api-runner-ssr" import pages from "./routes.json" import syncRequires from "./sync-requires" @@ -31,34 +30,21 @@ module.exports = (locals, callback) => { pathname: locals.path, }, }, - // For some reason we can't pass a component prop - // to StaticRouter like we do for BrowserRouter. - $(Route, { - component: location => - $( - syncRequires.layouts[`index`], - { ...location }, - $(Switch, null, [ - ...filteredPages.map(route => { - return $(Route, { - exact: true, - path: route.path, - component: props => - $(syncRequires.components[route.componentChunkName], { - ...props, - ...syncRequires.json[route.jsonName], - }), - }) - }), - $(Route, { - component: props => - $(syncRequires.components[noMatch.componentChunkName], { - ...props, - ...syncRequires.json[noMatch.jsonName], - }), - }), - ]) - ), + $(withRouter(syncRequires.layouts[`index`]), { + children: layoutProps => { + $(Route, { + component: routeProps => { + const props = layoutProps ? layoutProps : routeProps + const page = pages.find( + page => page.path === props.location.pathname + ) + return $(syncRequires.components[page.componentChunkName], { + ...props, + ...syncRequires.json[page.jsonName], + }) + }, + }) + }, }) ) diff --git a/www/src/templates/template-blog-post.js b/www/src/templates/template-blog-post.js index b8d8a8b5a663b..73145c591c276 100644 --- a/www/src/templates/template-blog-post.js +++ b/www/src/templates/template-blog-post.js @@ -6,7 +6,6 @@ import typography, { rhythm, scale } from "../utils/typography" const BlogPostTemplate = React.createClass({ render() { - console.log(this.props) const post = this.props.data.markdownRemark const twitterLine = post.frontmatter.author.twitter ? ` by ${post.frontmatter.author.twitter}`