Javascript react路由器dom中带BrowserRouter的动态basename
我在构建多租户SaaS解决方案时遇到了一个问题。对于每个租户,我希望他们使用子域,这样我就可以从url获取子域,调用RESTAPI返回关于该租户的数据 比如说,Javascript react路由器dom中带BrowserRouter的动态basename,javascript,reactjs,frontend,react-router-v4,react-router-dom,Javascript,Reactjs,Frontend,React Router V4,React Router Dom,我在构建多租户SaaS解决方案时遇到了一个问题。对于每个租户,我希望他们使用子域,这样我就可以从url获取子域,调用RESTAPI返回关于该租户的数据 比如说, 管理员(另一个应用程序完全是管理员应用程序)创建一个域名为:tenat1的租户 在本地系统上的租户应用程序中,我可以转到tenant1.localhost:3000。我得到了网址和域名。然后,我对域进行调用,以获取租户的主题(该主题存储在localStorage中) 不幸的是,我们公司部署在k8上,所以我无法模仿这种行为。因此,devO
tenat1
的租户李>
tenant1.localhost:3000
。我得到了网址和域名。然后,我对域进行调用,以获取租户的主题(该主题存储在localStorage中)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
请说明如何在路由器中使用dynamic basename,以便它可以接受:
localhost:3000/tenant1
localhost:3000/租户3
localhost:3000/租户2
等
它可以允许任何,我的应用程序处理输入的错误域我最终使用动态租户,代码如下
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)
类应用程序扩展组件{
状态={
域名:“
}
组件将安装(){
const{domain}=this.state;
const parsedData=window.location.pathname.split(“/”);
let domain=parsedData[1];
this.setState({domain:domain})
this.props.onGetTenant(域);
}
渲染(){
const{domain}=this.state;
返回(){
}
常量mapStateToProps=状态=>{
const{tenant}=状态;
返回{租户};
};
const mapDispatchToProps=(调度)=>{
返回{
onGetTenant:bindActionCreators(tenantActions.get,dispatch)
}
};
导出默认连接(mapStateToProps、mapDispatchToProps)(应用程序)
这对我使用react>16和react路由器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>
);
};
export const App=()=>{
返回(
);
};
导出常量LayoutRoot=()=>{
var{tenantId}=useParams();
//TODO:在此处添加一些验证,并在租户无效时通知用户
返回(
);
};
下面是一个codesandbox和我编写的实用程序:
在这种情况下,package.json中的“basename”应该是什么?我尝试过使用您的解决方案,但当我登录到我的应用程序时,basename没有改变。您可以共享您的PrivateRoute组件吗?package.json中的主页应该是什么?
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;
};