-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Accessing to the current pathContext from layout #3449
Comments
I'm having the same problem at the moment. |
cc @KyleAMathews @pieh do you have any thoughts on this? |
@monsieurnebo Your second idea wouldn't work because of current design as then your layout would need to be duplicated for all your pages - so for this it would be easier just to not use layouts at all and in your page components wrap your page "manually" in layout component: const page = ({data}) => {
return (
<LayoutThatWrapsPages pageData={data}>
{ // your actual page components }
</LayoutThatWrapsPages>
)
} Which is actually something that is desired to be able to do this way (and remove gatsby specific layouts construct) - #3830 (comment) - "What do we want" section. Just currently it's not viable to do - current chunk splitting would or could cause some load penalties in some cases and You would have to declare your global queries in each of your pages and that would cause data replication and heavier loads. Your first option is probably better for now, just I'm not sure if you can pass props to page component from layout. Would have to check that. |
@pieh I ended up using a "LayoutThatWrapsPages" in the meantime. It's working fine but I'm effrayed by the potential performances cost (I didn't dig up to verify this so far). |
If you have single layout it shouldn't be too bad - layout should be then placed in common chunk by webpack (along with react react-router etc - stuff that is used on every page). If you would have multiple layouts this might have more load consequences, but for single layout this should be fine (but I'm not 100% sure on that, actual build process is something I have yet to explore in depth, so probably would have to wait for @KyleAMathews comment on this) You can check https://www.npmjs.com/package/source-map-explorer to see if layout module is bundled in common chunk or in your templates chunk |
My website is having a modular layout. The full version of the layout is the following one:
The header & breadcrumb are always visibles and displaying some page-related information (e.g. page title), and the other sections don't appear on every single page. I created a layout component displaying these section (or not) according to the props passed from the page. PageLayoutexport default class PageLayout extends React.PureComponent {
static propTypes = {
headerTitle : PropTypes.string.isRequired,
breadcrumb : PropTypes.string,
sectionFoo : PropTypes.bool,
sectionBar : PropTypes.bool,
footer : PropTypes.bool,
legal : PropTypes.bool
};
// ...
render() {
const { headerTitle, breadcrumb, sectionFoo, sectionBar, footer, legal, children } = this.props;
return (
<div>
<Header title={headerTitle} />
{breadcrumb && this.renderBreadcrumb(breadcrumb)}
<main>
{children} // page
</main>
{sectionFoo && this.renderSectionFoo()}
{sectionBar && this.renderSectionBar()}
{footer && this.renderFooter()}
{legal && this.renderLegal()}
</div>
);
}
} Example PageIn this case, we only want to display the export default class ExamplePage extends React.PureComponent {
render() {
return (
<PageLayout
headerTitle="My amazing page"
breadcrumb="Breadcrumb blabla"
sectionFoo
footer
>
<div>
// The page content
</div>
</PageLayout>
);
}
} @KyleAMathews @pieh Does it sound right to you guys ? |
Yeah, this seems like it'd work great! |
Hello, I have the same problem for page name in header. I've tried to do wrapper for layout and nothing's changed. @monsieurnebo, I don't understand your example above. What will I do? My layout: import Helmet from "react-helmet";
import PropTypes from "prop-types";
import React from "react";
import withRoot from "../withRoot";
import { withStyles } from "material-ui/styles";
import Footer from "../components/Footer";
import Header from "../components/Header";
import Sidebar from "../components/Sidebar";
import "typeface-roboto";
const drawerWidth = 240;
const styles = theme => ({
root: {
flexGrow: 1,
zIndex: 1,
overflow: "hidden",
position: "relative",
display: "flex",
width: "100%"
},
toolbar: theme.mixins.toolbar,
content: {
width: "100%"
},
wrapper: {
display: "flex",
width: "100%",
flexFlow: "column nowrap",
justifyContent: "center",
alignItems: "center"
}
});
class IndexLayout extends React.Component {
constructor(props) {
super(props);
this.state = {
mobileOpen: false
};
}
handleDrawerToggle = () => {
this.setState({ mobileOpen: !this.state.mobileOpen });
};
render() {
const {
children,
classes,
data: { site: { siteMetadata: { description, keywords, title } } }
} = this.props;
const { mobileOpen } = this.state;
return (
<div className={classes.root}>
<Helmet
title={`${title} — ${description}`}
meta={[
{
name: "description",
content: description
},
{ name: "keywords", content: keywords }
]}
/>
<Sidebar
handleDrawerToggle={this.handleDrawerToggle}
mobileOpen={mobileOpen}
{...this.props}
/>
<div className={classes.wrapper}>
<Header
handleDrawerToggle={this.handleDrawerToggle}
{...this.props}
/>
<main className={classes.content} id="main">
<div className={classes.toolbar} />
{children({ ...this.props })}
</main>
<Footer {...this.props} />
</div>
</div>
);
}
}
IndexLayout.propTypes = {
children: PropTypes.func.isRequired,
classes: PropTypes.object.isRequired,
data: PropTypes.object.isRequired
};
export const IndexLayoutQuery = graphql`
query IndexLayoutQuery {
lessons: allMarkdownRemark(
sort: { fields: [frontmatter___title], order: ASC }
) {
edges {
node {
fields {
slug
}
frontmatter {
chapter
cover
date
lesson
title
type
}
id
}
}
}
site {
siteMetadata {
description
pathPrefix
rootDir
shortTitle
title
titleAlt
url
user {
description
location
name
site
}
}
}
}
`;
export default withRoot(withStyles(styles, { withTheme: true })(IndexLayout)); |
The layout component called inside pages is now the default behavior of Gatsby V2. I'm closing this. |
Hi,
I'm passing some data to my pages by the
context
option during theonCreatePage
action (gatsby-node.js). This data is available in the pages fromthis.props.pathContext
, but sometimes I need this data from the layouts.I have two solutions in my mind:
Declare a method in the layout that update its state, then pass it to the child (= page). At last, use it to pass the data from the page to the layout state.
Use a GraphQL query to access the page context from the layout, but I really don't understand how to query the "current page" from the layout.
The second option seems more clean & less odd. What's your opinion?
The text was updated successfully, but these errors were encountered: