[英]Add props to component of wrapped route in react router v4
我有共享相同行为、布局等的路由。我想将 props 从布局传递到路由内的那些组件(仪表板和登录)
我的 routes.js 文件如下
//imports omited
export default (
<AppLayout>
<Route component={Dashboard} path="/" key="/" />
<Route component={Login} path="/login" key="/login" />
</AppLayout>
);
AppLayout.js的render方法有这段代码
const childrenWithExtraProp = React.Children.map(this.props.children, (child) => {
return React.cloneElement(child, {
component: React.cloneElement(child.props.component, {
functions: {
updateMenuTitle: this.updateTitle //function
}
})
});
});
此代码导致许多错误:
Warning: Failed prop type: Invalid prop `component` of type `object` supplied to `Route`, expected `function`.
in Route
in AppHeader
in Router (created by BrowserRouter)
in BrowserRouter (created by App)
in App
Check the render method of `Route`.
in Route
in AppHeader
in Router (created by BrowserRouter)
in BrowserRouter (created by App)
in App
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of `Route`.
at invariant (invariant.js?7313:42)
at createFiberFromElement (react-dom.development.js?cada:5753)
at reconcileSingleElement (react-dom.development.js?cada:7531)
at reconcileChildFibers (react-dom.development.js?cada:7635)
at reconcileChildrenAtExpirationTime (react-dom.development.js?cada:7756)
at reconcileChildren (react-dom.development.js?cada:7747)
at finishClassComponent (react-dom.development.js?cada:7881)
at updateClassComponent (react-dom.development.js?cada:7850)
at beginWork (react-dom.development.js?cada:8225)
at performUnitOfWork (react-dom.development.js?cada:10224)
在我工作的最后一个项目中,我们在 Route 中使用了 Routes,但在 React-Router v4 中这是不允许的。
编辑:以前是这样的:
//Array of routes declared before
export default (
<Router history={browserHistory}>
<Route path="/" component={General}>
<IndexRoute component={Index} />
{routes}
</Route>
</Router>
);
我怀疑这是问题所在:
component: React.cloneElement(child.props.component, {
child.props.component
不是渲染组件(如<Dashbard />
),它是一个组件类(如Dashboard
)。 cloneElement
需要呈现的组件。 并且您不能显式地将 props extra 传递到组件类中。
有几种方法可以实现您正在做的事情。 克隆路线对我来说感觉“棘手”。
updateTitle
逻辑的高阶组件我个人会尝试制作一个高阶组件(一个接受组件类并返回一个组件类的函数)来添加此道具,并导出包含在其中的仪表板/登录组件。 稍微冗长但不那么棘手:
HOC 文件:
const WithExtraProp = (ContentComponent) => {
return WithPropWrapper extends Component {
updateMenuTitle() {...}
render() {
// Add extra props here
return <ContentComponent {...this.props} functions={{ updateMenuTitle: this.updateMenuTitle }}/>
}
}
}
export default WithExtraProp;
并在仪表板中
class Dashboard extends Component {...}
export default WithExtraProp(Dashboard);
用这个方法,你也可以做(虽然我不太喜欢)
<AppLayout>
<Route component={WithExtraProp(Dashboard)} path="/" key="/" />
<Route component={WithExtraProp(Login)} path="/login" key="/login" />
</AppLayout>
<Route render={} />
而不是component={}
添加道具如果你想保留你当前的设置,你隐式/“神奇地”添加 props ,我看不到不使用 Route 的render
prop 而不是component
。 这样你就可以渲染组件并正常传入 props。
您可以保持不变:
<Route component={Dashboard} path="/" key="/" />
和这样的事情:
const childrenWithExtraProp = React.Children.map(this.props.children, (child) => {
// Clone the <Route />, remove the `component` prop, add `render` prop
return React.cloneElement(child, {
// Remove the `component` prop from the Route, since you can't use
// `component` and `render` on a Route together. This way component
// just becomes an API for this withExtraPropClass to use to find
// the right component
component: null,
render = () => {
const ChildComponent = child.props.component;
const functions = {
updateMenuTitle: this.updateTitle //function
};
return <ChildComponent functions={functions} />;
}
})
});
});
AppLayout
成为高阶组件这与选项 1 相同,最终您执行以下操作:
//imports omited
export default (
<Route component={Dashboard} path="/" key="/" />
<Route component={Login} path="/login" key="/login" />
);
而AppLayout
是一个添加 prop 的高阶组件。
const AppLayout = (ContentComponent) => {
return WithPropWrapper extends Component {
updateMenuTitle() {...}
render() {
// Add extra props here
return (
<MyLayoutStuff>
<ContentComponent {...this.props} functions={{ updateMenuTitle: this.updateMenuTitle }}/>
</MyLayoutStuff>
);
}
}
}
export default AppLayout;
并导出包裹在布局中的组件:
class Dashboard extends Component {...}
export default AppLayout(Dashboard);
我个人一直在使用最接近 #3 的东西。 具体来说,我有一个类似dashboard/Dashboard.js
文件,在同一个文件夹中, dashboard/index.js
,它导出包裹在布局中的 Dashboard。 您可以在这个 React 样板 Github 文件夹中看到该模式的示例。
还有其他选择。 你可以制作一个<AppRoutes children=[{component: Dashboard, path="/"}, {...}] />
组件,它不必处理克隆。 如果你需要在<render>
之上对孩子做一些事情,我通常更喜欢将它们作为数组而不是子组件传入并映射它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.