title: React Router & Global Context
body: <p>I'm building an e-commerce website with React (my first ever React project) and I'm using React router to manage my pages.</p>
  
  <p>I've got the following component tree structure:</p>
  
  <pre><code>&lt;Router&gt;
    &lt;BrowserRouter&gt;
      &lt;Router&gt;
        &lt;withRouter(Base)&gt;
          &lt;Route&gt;
            &lt;Base&gt;
              &lt;BaseProvider&gt;
                &lt;Context.Provider&gt;
                  &lt;Header&gt;
                    &lt;PageContent&gt;
  </code></pre>
  
  <p>The standard React Router structure basically, and withRouter I've got the following:</p>
  
  <p><strong>Base.js</strong></p>
  
  <pre><code>import React, { Component } from 'react';
  import { withRouter } from 'react-router';
  
  import { Header } from './Header';
  import { Footer } from './Footer';
  import Provider from '../../BaseProvider';
  
  class Base extends Component {
    render() {
      return (
        &lt;Provider&gt;
          &lt;Header/&gt;
          &lt;div className="container"&gt;{this.props.children}&lt;/div&gt;
          &lt;Footer /&gt;
        &lt;/Provider&gt;
      );
    }
  }
  </code></pre>
  
  <p><strong>BaseProvider.js</strong></p>
  
  <pre><code>import React, { Component, createContext } from 'react';
  
  const Context = createContext();
  const { Provider, Consumer } = Context;
  
  class BaseProvider extends Component {
    state = {
      cart: [],
      basketTotal: 0,
      priceTotal: 0,
    };
  
    addProductToCart = product =&gt; {
      const cart = { ...this.state.cart };
      cart[product.id] = product;
      this.setState({ cart, basketTotal: Object.keys(cart).length });
    };
  
    render() {
      return (
        &lt;Provider
          value={{ state: this.state, addProductToCart: this.addProductToCart }}
        &gt;
          {this.props.children}
        &lt;/Provider&gt;
      );
    }
  }
  
  export { Consumer };
  export default BaseProvider;
  </code></pre>
  
  <p>This gives me a template essentially, so I just the children pages without having to include Header and Footer each time.</p>
  
  <p>If I want to use my global context I'm having to import it each time, and it seems like I've done something wrong as surely I should be able to use this on any page since it's exported in BaseProvider?</p>
  
  <p>If I was to visit the <strong>About page</strong>, I'd get the same component structure, but no access to the consumer without using:</p>
  
  <pre><code>import { Consumer } from '../../BaseProvider';
  </code></pre>
  
  <p>Why do I have to do this for each file even though it's exported and at the top level of my BaseProvider? It just seems such a bad pattern that I'd have to import it into about 20 files...</p>
  
  <p>Without importing it, I just get:</p>
  
  <pre><code>Line 67:  'Consumer' is not defined  no-undef
  </code></pre>
  
  <p>I tried just adding the contextType to base but I get: Warning: withRouter(Base): Function components do not support contextType.</p>
  
  <pre><code>Base.contextType = Consumer;
  </code></pre>
  
  <p>I feel like I've just implemented this wrong as surely this pattern should work a lot better.</p>