title: React SSR React Router Dom Switch, Route, Link "Invariant Failed"
body: <p>I beleive the proper discription of this issue is explained <a href="https://github.com/ReactTraining/react-router/issues/6789#issuecomment-502490351" rel="nofollow noreferrer">here</a> by timdorr. I tried exporting App.js from the bundle but get window undefined errors. SO still stuck</p>
  <p>SSR/Client React Router Dom &quot;Switch&quot; breaks for me with a &quot;Invariant Failed&quot;. I believe it says it has something to do with Switch not been allowed outside &quot;Router&quot;, which it is inside.</p>
  <p>The minimal project link is below, that may be easier way look at the project. I have listed the main files below</p>
  <p>1: SERVER SIDE RENDER ENDPOINT</p>
  <pre><code>// EXPRESS ROUTER
  const express = require(&quot;express&quot;);
  const aRouter = express.Router();
  
  // REACT UTILITIES
  import React from &quot;react&quot;;
  import { renderToNodeStream } from &quot;react-dom/server&quot;;
  import { StaticRouter } from &quot;react-router-dom&quot;;
  import { createMemoryHistory } from &quot;history&quot;;
  import Loadable from &quot;react-loadable&quot;;
  
  // REDUX UTILITIES
  import { init } from &quot;../src/module/store&quot;;
  import { Provider } from &quot;react-redux&quot;;
  
  // CUSTOM COMPONENTS
  import App from &quot;../src/App&quot;;
  
  // UTILITIES
  import fs from &quot;fs-extra&quot;;
  import renderUtils from &quot;../utils/renderUtils&quot;;
  
  // ASSETS
  import { initState } from &quot;../assets/store/init&quot;;
  
  aRouter.get([&quot;/&quot;, &quot;/home&quot;], async function (req, res) {
  
    console.log(&quot;RENDER HOME&quot;);
  
    try {
  
      // INITIAL WRITE TO CLIENT - START HEAD
      res.setHeader('Content-Type', 'text/html');
      res.write(&quot;&lt;!DOCTYPE html&gt;&quot;);
      res.write(&quot;&lt;html style='scrollbar-width: none;'&gt;&quot;);
  
      let headHTML = await fs.readFile(&quot;./public/head.html&quot;, &quot;utf-8&quot;);
      let scriptsHTML = await fs.readFile(&quot;./public/scripts.html&quot;, &quot;utf-8&quot;);
  
      res.write(headHTML);
      res.write(&quot;&lt;body&gt;&quot;);
      res.write(`&lt;div id = &quot;app-container&quot;&gt;`);
  
      // INITALISING STATE
      var initialState = initState();
      initialState.article.articles = {
        &quot;abcde&quot;: {
          title: &quot;My First Article&quot;,
          body: &quot;This is my first article&quot;
        },
        &quot;fghij&quot;: {
          title: &quot;My Second Article&quot;,
          body: &quot;This is my second article&quot;
        },
        &quot;klmno&quot;: {
          title: &quot;My Third Article&quot;,
          body: &quot;This is my third article&quot;
        }
      };
      initialState.article.fetched = true;
      initialState.ui.user = { type: &quot;&quot; };
      initialState.ui.global = {
        team: &quot;Arsenal&quot;,
        teamID: 19
      };
  
      const history = createMemoryHistory({ initialEntries: [req.originalUrl] });
      const store = init(history, initialState);
      
      // THE ISSUE SEEMS TO BE TO DO WITH THIS SERVER SIDE STATIC BROWSER AND THE CLIENT BORWSER ROUTER
      const stream = renderToNodeStream(
        &lt;Provider store = {store}&gt;
          &lt;StaticRouter history = {history} location = {req.originalUrl} context = {{}}&gt;
            &lt;App /&gt;
          &lt;/StaticRouter&gt;
        &lt;/Provider&gt;
      );
  
      stream.pipe(res, { end: false });
      stream.on(&quot;end&quot;, renderUtils.onRenderEnd.bind(this, res, store, scriptsHTML));
  
    } catch (err) { renderUtils.onRenderError.bind(this, res, &quot;RENDER HOME ERROR&quot;, err.message); }
  
  });
  
  var self = (module.exports = aRouter);
  </code></pre>
  <p>2: CLIENT INDEX</p>
  <pre><code>// REACT
  import React from &quot;react&quot;;
  import ReactDOM from &quot;react-dom&quot;;
  import Loadable from &quot;react-loadable&quot;;
  import { BrowserRouter } from &quot;react-router-dom&quot;;
  import { createMemoryHistory } from &quot;history&quot;;
  import { Provider } from &quot;react-redux&quot;;
  
  // REDUX
  import { init } from &quot;./module/store&quot;;
  
  // CREATE STORE
  let history = createMemoryHistory();
  let store = init(history, window.INITIAL_STATE);
  
  // MAIN APP COMPONENT
  import App from &quot;./App&quot;;
  
  // MOUNTED STYLES
  import &quot;./style/client/index.scss&quot;;
  
  const renderApp = () =&gt; {
    ReactDOM.hydrate(
      &lt;Provider store = {store}&gt;
        &lt;BrowserRouter history = {history}&gt;
          &lt;App /&gt;
        &lt;/BrowserRouter&gt;
      &lt;/Provider&gt;,
      document.getElementById(&quot;app-container&quot;)
    );
  };
  
  store.subscribe(() =&gt; renderApp());
  </code></pre>
  <p>3: APP - CLIENT</p>
  <pre><code>// REACT
  import React, { PureComponent } from &quot;react&quot;;
  import { Switch, Route } from &quot;react-router-dom&quot;;
  import PropTypes from &quot;prop-types&quot;;
  
  // REDUX STORE
  import { connect } from &quot;react-redux&quot;;
  import { getName, getAge, getPosition } from &quot;./module/user/userReducer&quot;;
  import { getUIElement, setUIElement } from &quot;./module/uiReducer&quot;;
  
  // IMPORT CUSTOM COMPONENTS
  import Routes from &quot;./Routes&quot;;
  
  class App extends PureComponent {
  
    componentDidMount = () =&gt; this.props.setUI(&quot;user&quot;, &quot;type&quot;, &quot;admin&quot;);
  
    render = () =&gt; {
      return (
        &lt;div className = &quot;app&quot;&gt;
          &lt;span&gt;My App&lt;/span&gt;
          &lt;span&gt;Name : {this.props.name}&lt;/span&gt;
          &lt;span&gt;Age : {this.props.age}&lt;/span&gt;
          &lt;span&gt;Position : {this.props.position}&lt;/span&gt;
          &lt;span&gt;Team : {this.props.team}&lt;/span&gt;
          &lt;span&gt;Team ID : {this.props.teamID}&lt;/span&gt;
          &lt;span&gt;Type : {this.props.type}&lt;/span&gt;
          &lt;div&gt;
            &lt;Switch&gt;
              &lt;Route path = &quot;/&quot; component = {MyLocation} /&gt;
              &lt;Route path = &quot;/contact&quot; render = {() =&gt; (&lt;MyLocation location = &quot;Contact&quot; /&gt;)} /&gt;
            &lt;/Switch&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      );
    };
  
  };
  
  App.propTypes = {
    name: PropTypes.string.isRequired,
    age: PropTypes.number.isRequired,
    position: PropTypes.string.isRequired,
    team: PropTypes.string.isRequired,
    teamID: PropTypes.number.isRequired,
    type: PropTypes.string.isRequired,
    setUI: PropTypes.func.isRequired
  };
  
  const mapStateToProps = state =&gt; ({
    name: getName(state),
    age: getAge(state),
    position: getPosition(state),
    team: getUIElement(state, &quot;global&quot;, &quot;team&quot;),
    teamID: getUIElement(state, &quot;global&quot;, &quot;teamID&quot;),
    type: getUIElement(state, &quot;user&quot;, &quot;type&quot;)
  });
  
  const mapDispatchToProps = dispatch =&gt; ({
    setUI: (component, element, value) =&gt; dispatch(setUIElement({ component, element, value }))
  });
  
  export default connect(
    mapStateToProps,
    mapDispatchToProps
  )(App);
  </code></pre>
  <p>The full minimal react app <a href="https://github.com/GaddMaster/gaddbox?fbclid=IwAR0st1_ZWNVJ-Z86m8dFZIPNTIs5XetU1b7jd-t7_IbCI08Jvss0KDzVuIg" rel="nofollow noreferrer">here</a></p>
  <p>It just breaks when I add the Switch and Routes. The Switch &quot;IS INSIDE&quot; the Browser Router. I have read articles which explain to send the same React Router Dom to the client, but I tried them explanations and they dont work for me.</p>
  <p>To run the project simply run &quot;yarn&quot;,  &quot;npm run build&quot; and &quot;npm start&quot;. The app has just one page with some filler text</p>
  <p>Issue : Breaks at Switch
  Required: Work at Switch
  Tried: Explantions that explain to bring same instance of react-router-dom to client from server and use webpack alies etc.</p>
  <h2>Timdorr (Shared at start of question) explains this.</h2>
  <h2>There is a new React.createContext API that we use in 5.0 to replace the legacy context usage. This involves creating a &quot;context&quot; pair, a set of Provider and Consumer components. We create that in a singleton module that is imported into Router and Link directly. In this new API, you have to use the exact same instance. Two separately-created contexts will never match up and won't be visible to each other.</h2>
  <p>Whats also funny is this works live on Heroku &quot;production&quot;, but doesnt work locally &quot;production&quot;. Im thinking heroku have some fallback code catching it.</p>
  <p>Any help be great;</p>
  <p>Daniel</p>