当各个子路由页面有公用代码部分,这部分公共代码会提出来放在父路由中,在dva@2中,由于使用了react-router@4,子路由只能放在父路由页面内,于是就会出现下面这种路由组织:
// 最外层父路由
......
export default ({ history, app }) => {
const App = dynamic({
app,
models: () => [appModel],
component: () => import('./routes/App'),
});
return (
<Router history={history}>
<Switch>
<Route path="/" component={App} />
</Switch>
</Router>
);
};
// 父页面内容示例
......
import Item from '../Item';
class App extends Component {
render() {
return (
<div className="app-wrap">
<Link to="/id">go to id</Link>
<Switch>
<Route path="/id" component={Item} />
</Switch>
</div>
);
}
}
const mapStateToProps = state => ({
appState: state.app
});
export default connect(mapStateToProps)(App);
那么在App这个页面中怎么去注册Item页面的model呢?
用 context 往下传 app ?
那样的话,把公用部分提取出来为一个组件,在每个页面中引入,在路由页面统一注册model,这样的实践方式更好吧?
可能这样的写法更好,这样我就可以在router.js中一起完成model的注册了:
export default ({ history, app }) => {
const App = dynamic({
app,
models: () => [appModel],
component: () => import('./routes/App'),
});
const Item = dynamic({
app,
models: () => [appModel],
component: () => import('./routes/Item'),
});
const OtherItem = dynamic({
app,
models: () => [appModel],
component: () => import('./routes/Other'),
});
return (
<Router history={history}>
<div>
<App />
<Switch>
<Route path="/id" component={Item} />
<Route path="/otherid" component={OtherItem} />
</Switch>
</div>
</Router>
);
};
App页面中也不需要创建新的子路由,无论子页面如何变动都会展示App页面中的内容。
虽然这样会有一个问题就是从DOM结构上,子路由并不是包裹在父元素内部的。。。
同样的问题,后来看了下官方的这个文档,
https://reacttraining.com/react-router/web/example/route-config
// wrap
// sub routes are added to any route it'll work
const RouteWithSubRoutes = (route) => (
)}/>
)
重点在子路由在父路由的 render 里嵌套生成。
@kobelin923 嗯,这个问题我已经转换思路解决了,我还是选择把路由都配置在了同一个页面内,对model的注册不会有影响,对页面结构也一样。
export default ({ history, app }) => {
const App = dynamic({
app,
models: () => [appModel],
component: () => import('./routes/App'),
});
const Item = dynamic({
app,
models: () => [appModel],
component: () => import('./routes/Item'),
});
const OtherItem = dynamic({
app,
models: () => [appModel],
component: () => import('./routes/OtherItem'),
});
return (
<Router history={history}>
<div className="root-wrap">
{/* 菜单栏 */}
<nav className="aside">
<Menu
mode="inline"
>
<Menu.Item key="/">
<Link to="/">首页</Link>
</Menu.Item>
<Menu.Item key="/id">
<Link to="/id">子页面</Link>
</Menu.Item>
<Menu.Item key="/otherid">
<Link to="/otherid">另一个子页面</Link>
</Menu.Item>
</Menu>
</nav>
<div className="main-content">
{/* 公共部分 */}
<App />
{/* 路由 */}
<Switch>
<Route exact path="/" render={() => (<div>这里会显示各个路由的内容</div>)} />
<Route path="/id" component={Item} />
<Route path="/otherid" component={OtherItem} />
</Switch>
</div>
</div>
</Router>
);
};
这就结束了啊,题主遇到的问题只是简单的嵌套,把layout放到了router里面来绕过这个问题,但可有更好的通用点的解决方案?
@sorrycc 是你说的这样更通用么?"用 context 往下传 app ?"
感觉layout和路由混在一起并不是一个很好的解决方案。
@wuzhuzhu 就算你把子路由放在组件里面还是和layout组合在一起的,react-router@v4的设计思想也是将Route作为普通React组件看待,让React Router在React的大框架下运转。
我是这样写的:
import React from 'react'
import modelExtend from 'dva-model-extend'
import { Route, Switch, Redirect } from 'react-router-dom'
import dynamic from 'dva/dynamic'
import app from '../../../index' // 从 /src/index.js 导入的app
import ClassBasicModel from './ClassMaintenance/basicModel'
function StepRoutes({ match }) {
const id = match.params.id
const routes = [{
path: `${match.url}/class-maintenance`,
models: () => [modelExtend(ClassBasicModel, { namespace: `class-maintenance-${id}` })],
component: () => import('./ClassMaintenance'),
}, {
path: `${match.url}/course-selection`,
models: () => [import('./CourseSelection/basicModel')],
component: () => import('../Steps/CourseSelection'),
}, {
path: `${match.url}/resource-arrangement`,
component: () => import('../Steps/ResourceArrangement'),
}, {
path: `${match.url}/walking-class-arrangement`,
component: () => import('../Steps/WalkingClassArrangement'),
}]
return (
<Switch>
<Route exact path={match.url} render={() => (<Redirect to={`${match.url}/class-maintenance`} />)} />
{
routes.map(({ path, ...dynamics }, index) => (
<Route
key={index}
exact
path={path}
component={dynamic({ app, ...dynamics })}
/>
))
}
</Switch>
)
}
export default StepRoutes
功能实现了, 但是会报错, 这是为什么 呢
warning.js?6327:33 Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.
Please check the code for the DynamicComponent component.
@zmayor 我也报同样的错误,你解决了吗?
并没有, 再不行只能放弃动态加载了
Most helpful comment
同样的问题,后来看了下官方的这个文档,
https://reacttraining.com/react-router/web/example/route-config
// wrap and use this everywhere instead, then when
// pass the sub-routes down to keep nesting
// sub routes are added to any route it'll work
const RouteWithSubRoutes = (route) => (
)}/>
)
重点在子路由在父路由的 render 里嵌套生成。