dynamic basename with BrowserRouter in react-router-dom

This worked for me using react >16 and react-router-dom v5

export const App = () => {
    return (
        <BrowserRouter>
            <Switch>
                <Route path="/:tenantId?" component={LayoutRoot} />
            </Switch>
        </BrowserRouter>
    );
};

export const LayoutRoot = () => {
    var { tenantId } = useParams();
     //TODO: add some validation here and inform user if tenant is invalid
    return (
        <BrowserRouter basename={tenantId}>
            <Switch>
                <Route path="/login" component={LoginComponent} />
                <Route path="/dashboard" component={DashboardComponent} />
            </Switch>
        </BrowserRouter>
    );
};

I finally used dynamic tenant with the following code

class App extends Component {

    state = {
        domain: ""
    }

    componentWillMount () {
        const { domain } = this.state;

        const parsedData = window.location.pathname.split("/"); 
        let domain = parsedData[1];
        this.setState({ domain: domain })
        this.props.onGetTenant(domain);                
    }

    render () {
        const { domain } = this.state;

        return () {
             <BrowserRouter basename={"/"+domain}>
                <Switch>
                    <Route exact path="/login" name="Login" component={Login} />
                    <Route exact path="/set-password/:token" name="Set Password" component={SetPassword} />
                    <PrivateRoute domain={domain} path="/" name="Default Layout" component={DefaultLayout} /> 
                 </Switch>              
             </BrowserRouter> 
    }

const mapStateToProps = state => {
    const { tenant} = state;
    return { tenant};
};

const mapDispatchToProps = (dispatch) => {
    return {
        onGetTenant: bindActionCreators( tenantActions.get, dispatch)
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(App)

You can render updates to your router's basename by using the key property. Any changes to the key value will cause the component to re-render.

Here's a code sandbox to demo: https://codesandbox.io/s/react-router-dom-dynamic-basename-forked-hnkk0?file=/index.js

You can hover or inspect the links in the sandbox to verify that their href values are correctly updating after changing the basename. You can also see that the hrefs won't update if you remove the key property from Router.

import React, { useState } from "react";
import { render } from "react-dom";
import { BrowserRouter, Link } from "react-router-dom";

const Root = () => {
  const [count, setCount] = useState(1);
  const basename = `basename-${count}`;

  return (
    <BrowserRouter basename={basename} key={basename}>
      <Link to="/link1">Link 1</Link>
      <br />
      <Link to="/link2">Link 2</Link>
      <br />
      Current basename: {basename}
      <br />
      <button onClick={() => setCount(count + 1)}>change basename</button>
    </BrowserRouter>
  );
};

render(<Root />, document.getElementById("root"));