簡體   English   中英

react-router-dom 中帶有 BrowserRouter 的動態基名

[英]dynamic basename with BrowserRouter in react-router-dom

請我在構建多租戶 SaaS 解決方案時遇到問題。 對於每個租戶,我希望他們使用一個子域,這樣我就可以從 url 獲取子域,調用 REST api 返回有關該租戶的數據。

例如,

  1. 管理員(完全是另一個應用程序 - 管理員應用程序)創建一個具有域名的租戶: tenant1
  2. 在我的本地系統上的租戶應用程序中,我能夠轉到tenant1.localhost:3000 我得到了網址,並得到了域名。 然后我與域進行調用以獲取租戶的主題(這存儲在 localStorage 中)。

不幸的是,我們部署在我公司的 k8 上,所以我無法模仿這種行為。 因此,devOps 團隊建議我在上下文中使用子域,從而擁有localhost:3000/tenant1 記住租戶是動態的,所以我試過這個:

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

然而,上面的解決方案使我的 url 為 localhost:3000/:tenant/login

請問我如何在路由器中使用動態基名,以便它可以接受:

localhost:3000/tenant1 localhost:3000/tenant3 localhost:3000/tenant2等等。

它可以允許任何,我的應用程序處理輸入的錯誤域

我終於使用了以下代碼的動態租戶

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)

這對我有用 react >16 和 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>
    );
};

這是我編寫的代碼沙盒和實用程序:

https://codesandbox.io/s/react-router-dom-dynamic-basename-xq9tj?file=/index.js

import urlJoin from 'url-join';

// it's important to have an identifier in their app
export const APP_ROOT_URL = '/my-app';

export const getBaseUrlPath = () => {
  const currentPath = document.location.pathname || APP_ROOT_URL;
  const startOfAppBase = currentPath.indexOf(APP_ROOT_URL);

  let base = currentPath;

  if (startOfAppBase !== -1) {
    base = currentPath.substr(0, startOfAppBase);
  }

  base = urlJoin(base, APP_ROOT_URL);

  return base;
};

您可以使用key屬性呈現對路由器basename的更新。 對鍵值的任何更改都會導致組件重新渲染。

這里有一個代碼沙箱來演示: https : //codesandbox.io/s/react-router-dom-dynamic-basename-forked-hnkk0?file=/index.js

您可以懸停或檢查沙箱中的鏈接,以驗證它們的href值在更改基本名稱后是否正確更新。 如果您從Router刪除key屬性,您還可以看到href不會更新。

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"));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM