{"componentChunkName":"component---src-templates-post-template-js","path":"/2018/05/22/react-context-api-with-gatsby/","result":{"data":{"mdx":{"frontmatter":{"title":"Use the React Context API with Gatsby","date":"2018 May 22nd"},"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"date\": \"2018-05-22T00:00:00.000Z\",\n  \"title\": \"Use the React Context API with Gatsby\",\n  \"tags\": [\"information\", \"learning\", \"guide\", \"gatsby\", \"api\"],\n  \"excerpt\": \"\",\n  \"published\": true\n};\n\nvar makeShortcode = function makeShortcode(name) {\n  return function MDXDefaultShortcode(props) {\n    console.warn(\"Component \" + name + \" was not imported, exported, or provided by MDXProvider as global scope\");\n    return mdx(\"div\", props);\n  };\n};\n\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"I\\u2019m a bit late to the party using the new \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://reactjs.org/docs/context.html\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"React Context API\"), \", I did\\nget to use it the other day at work, I also \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://github.com/spences10/settings/blob/35ba1ca3e9871c3ea6344ca2274ebbd327a18bed/globalVs.code-snippets#L74-L112\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"made a snippet\"), \" to\\nscaffold out a component for it.\"), mdx(\"p\", null, \"I had followed a couple of guides explaining how to use it and neither\\nof them as good as this great explanation of \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://www.youtube.com/watch?v=yzQ_XulhQFw\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"how to use it\"), \" from\\n\", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://twitter.com/leighchalliday\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"@leighchalliday\"), \", thank you Leigh \\uD83D\\uDE4F It\\u2019s a great use case which\\nhelped me understand how to use it.\"), mdx(\"p\", null, \"So, after doing this in a CRA project I decided to use it on one of my\\nGatsby projects. With Gatsby the layout is slightly different where\\nyou can have multiple layouts for differing sections of your app, so\\nthis lends well for passing context.\"), mdx(\"p\", null, \"One thing to bear in mind is that this is for my specific use case so\\nI\\u2019ll apologise upfront now if any of this is confusing, I\\u2019m trying to\\nget this documented to help me understand it too \\uD83D\\uDC4D\"), mdx(\"p\", null, \"With Gatsby if you want to use the React 16.3 then you will need to\\ninstall the Gatsby React next plugin:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"npm install gatsby-plugin-react-next\\n\")), mdx(\"p\", null, \"Gatsby uses React 16.2 I believe so you will need to use this plugin.\"), mdx(\"p\", null, \"Another thing you may need to do is:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-bash\"\n  }), \"npm i react react-dom\\nnpm un react react-dom\\n\")), mdx(\"p\", null, \"This may be because I was trying to use it in an old project, I\\u2019ve had\\nto do this on three projects now as I was getting \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"createContext\"), \" is\\nnot a function errors until I did this.\"), mdx(\"p\", null, \"One other thing you may want to consider if it appears nothing is\\nworking try using the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"npm ci\"), \" command. This is the npm 6+ version of\\ndeleting your \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"node_modules\"), \" folder and reinstalling. \\uD83E\\uDD13\"), mdx(\"p\", null, \"So let\\u2019s go through one of my favourite use cases at the moment and\\nadd theming support to a Gatsby site and use the React context API to\\nmanage the theme.\"), mdx(\"p\", null, \"You can see how theme a React app without the React Context API in my\\n\", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://scottspence.me/styled-components-getting-started\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"styled-components \\uD83D\\uDC85 getting started\"), \" post.\"), mdx(\"p\", null, \"For illustration I\\u2019ll go over it here now, you add the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ThemeProvider\"), \"\\nat the highest level in the application structure so that all\\ndescendants/children of the app can access it.\"), mdx(\"p\", null, \"I have already done this for my \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://scottspence.me\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"personal site\"), \" and now I\\u2019m going to\\ndo it \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"#\",\n    \"title\": \"this site, 👀\"\n  }), \"here\"), \" so let\\u2019s go through it together.\"), mdx(\"h2\", {\n    \"id\": \"lets-make-a-component\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", _extends({\n    parentName: \"h2\"\n  }, {\n    \"href\": \"#lets-make-a-component\",\n    \"aria-label\": \"lets make a component permalink\",\n    \"className\": \"anchor before\"\n  }), mdx(\"svg\", _extends({\n    parentName: \"a\"\n  }, {\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }), mdx(\"path\", _extends({\n    parentName: \"svg\"\n  }, {\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  })))), \"Let\\u2019s make a component!\"), mdx(\"p\", null, \"Ok, so everything in React is a component, that\\u2019s why I like it so\\nmuch - so let\\u2019s make a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SomethingContext.js\"), \" component, as I want to\\ndo the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"#\",\n    \"title\": \"things being using the styled components `ThemeProvider`\"\n  }), \"things\"), \" with the styled-components \\uD83D\\uDC85\"), mdx(\"p\", null, \"Let\\u2019s start by giving it an imaginative name:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"touch src/layouts/components/BlogThemeContext.js\\n\")), mdx(\"p\", null, \"There we go \\uD83D\\uDC4D\"), mdx(\"p\", null, \"Ok, the \\u2018things\\u2019 I want to do with the Context API are:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"change the styled-components \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"ThemeProvider\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"rotate the site hero patterns\")), mdx(\"p\", null, \"Now to scaffold out the context component, I have already mentioned\\nthe \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://github.com/spences10/settings/blob/71dc76fb8e11c176f4517431be57c021fb72411a/globalVs.code-snippets#L74-L111\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"VS Code snippet\"), \" for my own personal use which is the basic\\nstructure for the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Context\"), \" which is in two parts, a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Provider\"), \" and a\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Consumer\")), mdx(\"p\", null, \"Let\\u2019s create the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Context\"), \" and the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Consumer\"), \" in this component.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Using the snippet it should look something like this:\")), mdx(\"h6\", {\n    \"id\": \"srclayoutscomponentsblogthemecontextjs\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", _extends({\n    parentName: \"h6\"\n  }, {\n    \"href\": \"#srclayoutscomponentsblogthemecontextjs\",\n    \"aria-label\": \"srclayoutscomponentsblogthemecontextjs permalink\",\n    \"className\": \"anchor before\"\n  }), mdx(\"svg\", _extends({\n    parentName: \"a\"\n  }, {\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }), mdx(\"path\", _extends({\n    parentName: \"svg\"\n  }, {\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  })))), mdx(\"inlineCode\", {\n    parentName: \"h6\"\n  }, \"src/layouts/components/BlogThemeContext.js\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"import React from 'react'\\n// Context is made up of two things\\n// Provider - Single as close to top level as possible\\n// Consumer - Multiple have multiple consumers\\nexport const BlogThemeContext = React.createContext()\\n\\nexport class BlogThemeProvider extends React.Component {\\n  state = {\\n    item1: 1,\\n    item2: 2,\\n  }\\n\\n  // add function here\\n  functionHere = () => {\\n    this.setState({\\n      item1: 2,\\n      item2: 3,\\n    })\\n  }\\n  render() {\\n    return (\\n      <BlogThemeContext.Provider\\n        value={{\\n          ...this.state,\\n          functionHere: this.functionHere,\\n        }}\\n      >\\n        {this.props.children}\\n      </BlogThemeContext.Provider>\\n    )\\n  }\\n}\\n\")), mdx(\"p\", null, \"So the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"props\"), \" passed into the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<BlogThemeContext.Provider>\"), \" is the\\nstate and the methods contained in \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"BlogThemeProvider\"), \" these can then\\nbe accessed throughout the app by using the\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<BlogThemeContext.Consumer>\"), \".\"), mdx(\"p\", null, \"Now let\\u2019s add the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"BlogThemeProvider\"), \" at the top level of our app so\\nthat the state and functions of the provider can are accessible for\\nthe children of the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"layout/index.js\"), \".\"), mdx(\"p\", null, \"This is what it looks like before adding the context provider, you\\u2019ll\\nnotice that the styled-components \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ThemeProvider\"), \" is a top level\\ncomponent here.\"), mdx(\"h6\", {\n    \"id\": \"srclayoutsindexjs\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", _extends({\n    parentName: \"h6\"\n  }, {\n    \"href\": \"#srclayoutsindexjs\",\n    \"aria-label\": \"srclayoutsindexjs permalink\",\n    \"className\": \"anchor before\"\n  }), mdx(\"svg\", _extends({\n    parentName: \"a\"\n  }, {\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }), mdx(\"path\", _extends({\n    parentName: \"svg\"\n  }, {\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  })))), mdx(\"inlineCode\", {\n    parentName: \"h6\"\n  }, \"src/layouts/index.js\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const TemplateWrapper = ({ children }) => (\\n  <ThemeProvider theme={theme}>\\n    <PageContainer>\\n      <Helmet title={nameContent} meta={siteMeta} />\\n      <Header />\\n      <Main>{children()}</Main>\\n      <Footer />\\n    </PageContainer>\\n  </ThemeProvider>\\n)\\n\")), mdx(\"p\", null, \"Now we already have the styled-components \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ThemeProvider\"), \" which\\nreceives a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"theme\"), \" object, and we want to manage the theme in our\\ncontext provider. So let\\u2019s import the existing theme from the\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"globalStyle\"), \" module into \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"BlogThemeContext\"), \" and add \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"theme\"), \" to the\\nstate of the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"BlogThemeProvider\"), \":\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"import React from 'react'\\nimport PropTypes from 'prop-types'\\n\\nimport { theme } from '../../theme/globalStyle'\\n\\n// Context is made up of two things\\n// Provider - Single as close to top level as possible\\n// Consumer - Multiple have multiple consumers\\nexport const BlogThemeContext = React.createContext()\\n\\nexport class BlogThemeProvider extends React.Component {\\n  state = {\\n    theme,\\n  }\\n\\n  // add function here\\n  functionHere = () => {\\n    this.setState({\\n      item1: 2,\\n      item2: 3,\\n    })\\n  }\\n  render() {\\n    return (\\n      <BlogThemeContext.Provider\\n        value={{\\n          ...this.state,\\n          functionHere: this.functionHere,\\n        }}\\n      >\\n        {this.props.children}\\n      </BlogThemeContext.Provider>\\n    )\\n  }\\n}\\n\\nBlogThemeProvider.propTypes = {\\n  children: PropTypes.any,\\n}\\n\")), mdx(\"p\", null, \"While we\\u2019re here let\\u2019s also add the function to handle the theme\\nchanging by replacing the dummy \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"functionHere\"), \" function in the snippet\\nand also bring in the themes we want to switch between.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"import React from 'react'\\nimport PropTypes from 'prop-types'\\n\\nimport { theme1, theme2 } from '../../theme/globalStyle'\\n\\nexport const BlogThemeContext = React.createContext()\\n\\nexport class BlogThemeProvider extends React.Component {\\n  state = {\\n    theme,\\n  }\\n\\n  handleThemeChange = e => {\\n    let theme = e.target.value\\n    theme === 'theme1' ? (theme = theme1) : (theme = theme2)\\n    this.setState({ theme })\\n  }\\n  render() {\\n    return (\\n      <BlogThemeContext.Provider\\n        value={{\\n          ...this.state,\\n          handleThemeChange: this.handleThemeChange,\\n        }}\\n      >\\n        {this.props.children}\\n      </BlogThemeContext.Provider>\\n    )\\n  }\\n}\\n\\nBlogThemeProvider.propTypes = {\\n  children: PropTypes.any,\\n}\\n\")), mdx(\"h2\", {\n    \"id\": \"use-the-contextconsumer\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", _extends({\n    parentName: \"h2\"\n  }, {\n    \"href\": \"#use-the-contextconsumer\",\n    \"aria-label\": \"use the contextconsumer permalink\",\n    \"className\": \"anchor before\"\n  }), mdx(\"svg\", _extends({\n    parentName: \"a\"\n  }, {\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }), mdx(\"path\", _extends({\n    parentName: \"svg\"\n  }, {\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  })))), \"Use the \", mdx(\"inlineCode\", {\n    parentName: \"h2\"\n  }, \"Context.Consumer\")), mdx(\"p\", null, \"So, now, let\\u2019s use it, right? The way to use is much like with the\\nstyled-component \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ThemeProvider\"), \", import your \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<ThemeSelectProvider>\"), \"\\nthen you can use the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<ThemeSelectContext.Consumer>\"), \" to access the\\nfunctions and state of the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"BlogThemeContext\"), \" via the\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<ThemeSelectProvider>\")), mdx(\"p\", null, \"The child of a consumer is a function, so rather than have your app\\nbeing returned like you would with a normal React component like this:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"<Wrapper>\\n  <Child />\\n</Wrapper>\\n\")), mdx(\"p\", null, \"So you need to embed a function like this:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"<Wrapper>{() => <Child />}</Wrapper>\\n\")), mdx(\"p\", null, \"So you\\u2019re returning the (in this example, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<Child />\"), \") app as the\\nresult of the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<Context.Consumer>\"), \" function, here we can also get any\\nof the properties or state from the Context, in my use case here I\\nwant to get the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"theme\"), \" prop out of the Context provider \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"value\"), \"\\n(\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<BlogThemeProvider>\"), \") so we\\u2019ll use ES6 destructuring to pull out the\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"theme\"), \" object.\"), mdx(\"p\", null, \"The styled-components \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ThemeProvider\"), \" can now use the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"theme\"), \" object\\nsupplied by the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<BlogThemeContext.Consumer>\"), \" so it\\u2019s safe to remove\\nthe import from \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"globalStyle\"), \".\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const TemplateWrapper = ({ children }) => (\\n  <BlogThemeProvider>\\n    <BlogThemeContext.Consumer>\\n      {({ theme }) => (\\n        <ThemeProvider theme={theme}>\\n          <PageContainer>\\n            <Helmet title={nameContent} meta={siteMeta} />\\n            <Header />\\n            <Main>{children()}</Main>\\n            <Footer />\\n          </PageContainer>\\n        </ThemeProvider>\\n      )}\\n    </BlogThemeContext.Consumer>\\n  </BlogThemeProvider>\\n)\\n\")), mdx(\"p\", null, \"There\\u2019s also a template \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"src/template/blog-posts.js\"), \" which Gatsby uses\\nto generate the posts in this blog, let\\u2019s make it the same, let\\u2019s wrap\\nthe app in the return function for the context consumer, before it\\nlooked like this:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const Template = ({ data, pathContext }) => {\\n  const { markdownRemark: post } = data\\n  const { frontmatter, html } = post\\n  const { title, date } = frontmatter\\n  const { next, prev } = pathContext\\n\\n  return (\\n    <PostWrapper border={({ theme }) => theme.primary.light}>\\n      <Helmet title={`${title} - blog.scottspence.me`} />\\n      <Title>{title}</Title>\\n      <TitleDate>{date}</TitleDate>\\n      ....\\n\")), mdx(\"p\", null, \"Now it looks like this:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const Template = ({ data, pathContext }) => {\\n  const { markdownRemark: post } = data\\n  const { frontmatter, html } = post\\n  const { title, date } = frontmatter\\n  const { next, prev } = pathContext\\n\\n  return (\\n    <BlogThemeProvider>\\n      <BlogThemeContext.Consumer>\\n        {({ theme }) => (\\n          <PostWrapper border={({ theme }) => theme.primary.light}>\\n            <Helmet title={`${title} - blog.scottspence.me`} />\\n            <Title>{title}</Title>\\n            <TitleDate>{date}</TitleDate>\\n            ....\\n\")), mdx(\"h2\", {\n    \"id\": \"add-a-themeselect-component\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", _extends({\n    parentName: \"h2\"\n  }, {\n    \"href\": \"#add-a-themeselect-component\",\n    \"aria-label\": \"add a themeselect component permalink\",\n    \"className\": \"anchor before\"\n  }), mdx(\"svg\", _extends({\n    parentName: \"a\"\n  }, {\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }), mdx(\"path\", _extends({\n    parentName: \"svg\"\n  }, {\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  })))), \"Add a ThemeSelect component\"), mdx(\"p\", null, \"The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ThemeSelect\"), \" component is a select component I have used several\\ntimes now, \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://github.com/spences10/scottspence.me/blob/master/src/components/ThemeSelect.js\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"here\\u2019s the source\"), \" from my personal site, it\\u2019s what we\\u2019re\\ngoing to use to handle the theme change, it will use the\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"handleThemeChange\"), \" method in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"BlogThemeContext\"), \" so we better use\\na Context consumer to access the method:\"), mdx(\"h6\", {\n    \"id\": \"srclayoutscomponentsfooterjs\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", _extends({\n    parentName: \"h6\"\n  }, {\n    \"href\": \"#srclayoutscomponentsfooterjs\",\n    \"aria-label\": \"srclayoutscomponentsfooterjs permalink\",\n    \"className\": \"anchor before\"\n  }), mdx(\"svg\", _extends({\n    parentName: \"a\"\n  }, {\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }), mdx(\"path\", _extends({\n    parentName: \"svg\"\n  }, {\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  })))), mdx(\"inlineCode\", {\n    parentName: \"h6\"\n  }, \"src/layouts/components/Footer.js\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"<BlogThemeContext.Consumer>\\n  {({ handleThemeChange }) => (\\n    <ThemeSelectWrapper>\\n      <ThemeSelect handleThemeChange={handleThemeChange} />\\n    </ThemeSelectWrapper>\\n  )}\\n</BlogThemeContext.Consumer>\\n\")), mdx(\"p\", null, \"Now if we have a look at the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"state\"), \" in the React dev tools we can see\\nthe font changing with the selection of the theme change, much like in\\nthe \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://scottspence.me/styled-components-getting-started\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"styled-components \\uD83D\\uDC85 getting started\"), \" post.\"), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://thepracticaldev.s3.amazonaws.com/i/r1b8qgu6lm5xjjondse7.gif\",\n    \"alt\": null\n  }))), mdx(\"p\", null, \"Ok, success \\uD83D\\uDCAF \\uD83D\\uDC4C now onto the background switching/transition thingy.\"), mdx(\"h2\", {\n    \"id\": \"switch-hero-background-patterns\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", _extends({\n    parentName: \"h2\"\n  }, {\n    \"href\": \"#switch-hero-background-patterns\",\n    \"aria-label\": \"switch hero background patterns permalink\",\n    \"className\": \"anchor before\"\n  }), mdx(\"svg\", _extends({\n    parentName: \"a\"\n  }, {\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }), mdx(\"path\", _extends({\n    parentName: \"svg\"\n  }, {\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  })))), \"Switch hero (background patterns)\"), mdx(\"p\", null, \"So, right now to switch between \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://twitter.com/steveschoger\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"Steve Schoger\"), \"\\u2019s awesome \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"http://www.heropatterns.com/\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"hero\\npatterns\"), \" I have a function sitting in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"globalStyle\"), \" module which\\nreturns a random HERO pattern:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"export const randoHero = () => {\\n  const keys = Object.keys(HERO)\\n  return HERO[keys[(keys.length * Math.random()) << 0]]\\n}\\n\")), mdx(\"p\", null, \"This function sets the background on the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"body\"), \" each reload with a\\nrandom key from the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"HERO\"), \" object, now I\\u2019m going to move that to the\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"componentDidMount()\"), \" of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"BlogThemeContext.Provider\"), \" so (for now) it\\nselects a random key from the object every ten seconds:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"export class BlogThemeProvider extends React.Component {\\n  state = {\\n    theme: theme1,\\n    background: HERO[0]\\n  }\\n\\n  handleThemeChange = e => {\\n    let theme = e.target.value\\n    theme === 'theme1' ? (theme = theme1) : (theme = theme2)\\n    this.setState({ theme })\\n  }\\n\\n  componentDidMount() {\\n    this.interval = setInterval(() => {\\n      const keys = Object.keys(HERO)\\n      const background =\\n        HERO[keys[(keys.length * Math.random()) << 0]]\\n\\n      this.setState({ background })\\n    }, 10 * 1000)\\n  }\\n\\n  render() {\\n  ....\\n\")), mdx(\"p\", null, \"Now to find somewhere in the app that can change the background! As I\\nmentioned before the background for the page was set on the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"body\"), \" via\\nstyled-components \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"injectGlobal\"), \" I now want to access the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"background\"), \"\\nprop from Context so I have moved this to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"src/layouts/index.js\"), \". I\\nalready have the Context consumer added for the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"theme\"), \" so let\\u2019s\\ndestructure the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"background\"), \" prop out as well:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const TemplateWrapper = ({ children }) => (\\n  <BlogThemeProvider>\\n    <BlogThemeContext.Consumer>\\n      {({ theme, background }) => (\\n        <ThemeProvider theme={theme}>\\n          <PageContainer background={background}>\\n            <Helmet title={nameContent} meta={siteMeta} />\\n            <Header />\\n            <Main>{children()}</Main>\\n            <Footer />\\n          </PageContainer>\\n          ....\\n\")), mdx(\"p\", null, \"Now use the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"background\"), \" prop in the main wrapper \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"PageContainer\")), mdx(\"p\", null, \"We\\u2019re passing the both the background image and colour as\\nstyled-component props now.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const PageContainer = styled.div`\\n  background-color: ${props => props.theme.background};\\n  background-image: url(\\\"${props => props.background}\\\");\\n  background-attachment: fixed;\\n\")), mdx(\"p\", null, \"That\\u2019s it! We have used the React Context API to access state and use\\nit at (two) different points in the app.\"), mdx(\"h2\", {\n    \"id\": \"thanks-for-reading-\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", _extends({\n    parentName: \"h2\"\n  }, {\n    \"href\": \"#thanks-for-reading-\",\n    \"aria-label\": \"thanks for reading  permalink\",\n    \"className\": \"anchor before\"\n  }), mdx(\"svg\", _extends({\n    parentName: \"a\"\n  }, {\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }), mdx(\"path\", _extends({\n    parentName: \"svg\"\n  }, {\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  })))), \"Thanks for reading \\uD83D\\uDE4F\"), mdx(\"p\", null, \"Thanks you for looking at all the code walls!\"), mdx(\"p\", null, \"If you have any feedback \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://scottspence.me/contact\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"please get in touch\")), mdx(\"p\", null, \"You can find all the source code to this on my repo for this project\\nhere: \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://thelocalhost.io/\",\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }), \"https://thelocalhost.io/\")));\n}\n;\nMDXContent.isMDXComponent = true;","excerpt":"I'm a bit late to the party using the new  React Context API , I did\nget to use it the other day at work, I also  made a snippet  to…","tableOfContents":{"items":[{"url":"#lets-make-a-component","title":"Let's make a component!","items":[{"items":[{"items":[{"items":[{"url":"#srclayoutscomponentsblogthemecontextjs","title":"src/layouts/components/BlogThemeContext.js"},{"url":"#srclayoutsindexjs","title":"src/layouts/index.js"}]}]}]}]},{"url":"#use-the-contextconsumer","title":"Use the Context.Consumer"},{"url":"#add-a-themeselect-component","title":"Add a ThemeSelect component","items":[{"items":[{"items":[{"items":[{"url":"#srclayoutscomponentsfooterjs","title":"src/layouts/components/Footer.js"}]}]}]}]},{"url":"#switch-hero-background-patterns","title":"Switch hero (background patterns)"},{"url":"#thanks-for-reading-","title":"Thanks for reading 🙏"}]},"timeToRead":4,"fields":{"slug":"/2018/05/22/react-context-api-with-gatsby/","editLink":"https://github.com/spences10/thelocalhost/edit/authoring/posts/2018/05/22/react-context-api-with-gatsby/index.md"}}},"pageContext":{"slug":"/2018/05/22/react-context-api-with-gatsby/","previous":{"id":"ed6fd5dc-a693-5010-853b-166c0ba8a30e","excerpt":"We're going to style the basic create react app with styled-components\nto look something like this: But first, preamble✨: I have always struggled with styling sites, it\nseems to be an aspect of starting web development that is either an\nafterthought…","frontmatter":{"title":"styled-components 💅 getting started","date":"2018-04-03T00:00:00.000Z"},"fields":{"slug":"/2018/04/03/styled-components/"}},"next":{"id":"48b64a49-83e1-53cc-9614-71398bce96b6","excerpt":"I thought I'd set up this blog with some sort of build pipeline, the\nintention was to have a good Continuous Integration pipeline so that\nif there were any issues when building the site that I wouldn't push a\nbroken build. No one wants to see that…","frontmatter":{"title":"Making a CI pipeline with Travis CI","date":"2018-05-28T00:00:00.000Z"},"fields":{"slug":"/2018/05/28/travis-ci/"}}}}}