[英]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.